1 /* Copyright (c) 2015-2016 The Khronos Group Inc.
2  * Copyright (c) 2015-2016 Valve Corporation
3  * Copyright (c) 2015-2016 LunarG, Inc.
4  * Copyright (C) 2015-2016 Google Inc.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and/or associated documentation files (the "Materials"), to
8  * deal in the Materials without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Materials, and to permit persons to whom the Materials
11  * are furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice(s) and this permission notice shall be included
14  * in all copies or substantial portions of the Materials.
15  *
16  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  *
20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
23  * USE OR OTHER DEALINGS IN THE MATERIALS
24  *
25  * Author: Ian Elliott <ian@lunarg.com>
26  * Author: Ian Elliott <ianelliott@google.com>
27  */
28 
29 #include <stdio.h>
30 #include <string.h>
31 #include <vk_loader_platform.h>
32 #include <vulkan/vk_icd.h>
33 #include "swapchain.h"
34 #include "vk_layer_extension_utils.h"
35 #include "vk_enum_string_helper.h"
36 #include "vk_layer_utils.h"
37 
38 static int globalLockInitialized = 0;
39 static loader_platform_thread_mutex globalLock;
40 
41 // The following is for logging error messages:
42 static std::unordered_map<void *, layer_data *> layer_data_map;
43 
44 template layer_data *get_my_data_ptr<layer_data>(void *data_key, std::unordered_map<void *, layer_data *> &data_map);
45 
46 static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
47 
48 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkEnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pCount,VkExtensionProperties * pProperties)49 vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
50     return util_GetExtensionProperties(ARRAY_SIZE(instance_extensions), instance_extensions, pCount, pProperties);
51 }
52 
vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,const char * pLayerName,uint32_t * pCount,VkExtensionProperties * pProperties)53 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
54                                                                                     const char *pLayerName, uint32_t *pCount,
55                                                                                     VkExtensionProperties *pProperties) {
56     if (pLayerName == NULL) {
57         dispatch_key key = get_dispatch_key(physicalDevice);
58         layer_data *my_data = get_my_data_ptr(key, layer_data_map);
59         return my_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
60     } else {
61         return util_GetExtensionProperties(0, nullptr, pCount, pProperties);
62     }
63 }
64 
65 static const VkLayerProperties swapchain_layers[] = {{
66     "VK_LAYER_LUNARG_swapchain", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer",
67 }};
68 
69 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkEnumerateInstanceLayerProperties(uint32_t * pCount,VkLayerProperties * pProperties)70 vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
71     return util_GetLayerProperties(ARRAY_SIZE(swapchain_layers), swapchain_layers, pCount, pProperties);
72 }
73 
74 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,uint32_t * pCount,VkLayerProperties * pProperties)75 vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
76     return util_GetLayerProperties(ARRAY_SIZE(swapchain_layers), swapchain_layers, pCount, pProperties);
77 }
78 
createDeviceRegisterExtensions(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,VkDevice device)79 static void createDeviceRegisterExtensions(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
80                                            VkDevice device) {
81     uint32_t i;
82     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
83     layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
84 
85     VkLayerDispatchTable *pDisp = my_device_data->device_dispatch_table;
86     PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr;
87 
88     pDisp->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR)gpa(device, "vkCreateSwapchainKHR");
89     pDisp->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)gpa(device, "vkDestroySwapchainKHR");
90     pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)gpa(device, "vkGetSwapchainImagesKHR");
91     pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)gpa(device, "vkAcquireNextImageKHR");
92     pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR)gpa(device, "vkQueuePresentKHR");
93     pDisp->GetDeviceQueue = (PFN_vkGetDeviceQueue)gpa(device, "vkGetDeviceQueue");
94 
95     SwpPhysicalDevice *pPhysicalDevice = &my_instance_data->physicalDeviceMap[physicalDevice];
96     if (pPhysicalDevice) {
97         my_device_data->deviceMap[device].pPhysicalDevice = pPhysicalDevice;
98         pPhysicalDevice->pDevice = &my_device_data->deviceMap[device];
99     } else {
100         // TBD: Should we leave error in (since Swapchain really needs this
101         // link)?
102         log_msg(my_instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
103                 (uint64_t)physicalDevice, __LINE__, SWAPCHAIN_INVALID_HANDLE, "Swapchain",
104                 "vkCreateDevice() called with a non-valid VkPhysicalDevice.");
105     }
106     my_device_data->deviceMap[device].device = device;
107     my_device_data->deviceMap[device].swapchainExtensionEnabled = false;
108 
109     // Record whether the WSI device extension was enabled for this VkDevice.
110     // No need to check if the extension was advertised by
111     // vkEnumerateDeviceExtensionProperties(), since the loader handles that.
112     for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
113         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
114 
115             my_device_data->deviceMap[device].swapchainExtensionEnabled = true;
116         }
117     }
118 }
119 
createInstanceRegisterExtensions(const VkInstanceCreateInfo * pCreateInfo,VkInstance instance)120 static void createInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
121     uint32_t i;
122     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
123     VkLayerInstanceDispatchTable *pDisp = my_data->instance_dispatch_table;
124     PFN_vkGetInstanceProcAddr gpa = pDisp->GetInstanceProcAddr;
125 #ifdef VK_USE_PLATFORM_ANDROID_KHR
126     pDisp->CreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR)gpa(instance, "vkCreateAndroidSurfaceKHR");
127 #endif // VK_USE_PLATFORM_ANDROID_KHR
128 #ifdef VK_USE_PLATFORM_MIR_KHR
129     pDisp->CreateMirSurfaceKHR = (PFN_vkCreateMirSurfaceKHR)gpa(instance, "vkCreateMirSurfaceKHR");
130     pDisp->GetPhysicalDeviceMirPresentationSupportKHR =
131         (PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
132 #endif // VK_USE_PLATFORM_MIR_KHR
133 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
134     pDisp->CreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR)gpa(instance, "vkCreateWaylandSurfaceKHR");
135     pDisp->GetPhysicalDeviceWaylandPresentationSupportKHR =
136         (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
137 #endif // VK_USE_PLATFORM_WAYLAND_KHR
138 #ifdef VK_USE_PLATFORM_WIN32_KHR
139     pDisp->CreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)gpa(instance, "vkCreateWin32SurfaceKHR");
140     pDisp->GetPhysicalDeviceWin32PresentationSupportKHR =
141         (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
142 #endif // VK_USE_PLATFORM_WIN32_KHR
143 #ifdef VK_USE_PLATFORM_XCB_KHR
144     pDisp->CreateXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR)gpa(instance, "vkCreateXcbSurfaceKHR");
145     pDisp->GetPhysicalDeviceXcbPresentationSupportKHR =
146         (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
147 #endif // VK_USE_PLATFORM_XCB_KHR
148 #ifdef VK_USE_PLATFORM_XLIB_KHR
149     pDisp->CreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR)gpa(instance, "vkCreateXlibSurfaceKHR");
150     pDisp->GetPhysicalDeviceXlibPresentationSupportKHR =
151         (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
152 #endif // VK_USE_PLATFORM_XLIB_KHR
153     pDisp->DestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)gpa(instance, "vkDestroySurfaceKHR");
154     pDisp->GetPhysicalDeviceSurfaceSupportKHR =
155         (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceSupportKHR");
156     pDisp->GetPhysicalDeviceSurfaceCapabilitiesKHR =
157         (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
158     pDisp->GetPhysicalDeviceSurfaceFormatsKHR =
159         (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR");
160     pDisp->GetPhysicalDeviceSurfacePresentModesKHR =
161         (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)gpa(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR");
162 
163     // Remember this instance, and whether the VK_KHR_surface extension
164     // was enabled for it:
165     my_data->instanceMap[instance].instance = instance;
166     my_data->instanceMap[instance].surfaceExtensionEnabled = false;
167 #ifdef VK_USE_PLATFORM_ANDROID_KHR
168     my_data->instanceMap[instance].androidSurfaceExtensionEnabled = false;
169 #endif // VK_USE_PLATFORM_ANDROID_KHR
170 #ifdef VK_USE_PLATFORM_MIR_KHR
171     my_data->instanceMap[instance].mirSurfaceExtensionEnabled = false;
172 #endif // VK_USE_PLATFORM_MIR_KHR
173 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
174     my_data->instanceMap[instance].waylandSurfaceExtensionEnabled = false;
175 #endif // VK_USE_PLATFORM_WAYLAND_KHR
176 #ifdef VK_USE_PLATFORM_WIN32_KHR
177     my_data->instanceMap[instance].win32SurfaceExtensionEnabled = false;
178 #endif // VK_USE_PLATFORM_WIN32_KHR
179 #ifdef VK_USE_PLATFORM_XCB_KHR
180     my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = false;
181 #endif // VK_USE_PLATFORM_XCB_KHR
182 #ifdef VK_USE_PLATFORM_XLIB_KHR
183     my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = false;
184 #endif // VK_USE_PLATFORM_XLIB_KHR
185 
186     // Record whether the WSI instance extension was enabled for this
187     // VkInstance.  No need to check if the extension was advertised by
188     // vkEnumerateInstanceExtensionProperties(), since the loader handles that.
189     for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
190         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) {
191 
192             my_data->instanceMap[instance].surfaceExtensionEnabled = true;
193         }
194 #ifdef VK_USE_PLATFORM_ANDROID_KHR
195         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0) {
196 
197             my_data->instanceMap[instance].androidSurfaceExtensionEnabled = true;
198         }
199 #endif // VK_USE_PLATFORM_ANDROID_KHR
200 #ifdef VK_USE_PLATFORM_MIR_KHR
201         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_MIR_SURFACE_EXTENSION_NAME) == 0) {
202 
203             my_data->instanceMap[instance].mirSurfaceExtensionEnabled = true;
204         }
205 #endif // VK_USE_PLATFORM_MIR_KHR
206 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
207         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME) == 0) {
208 
209             my_data->instanceMap[instance].waylandSurfaceExtensionEnabled = true;
210         }
211 #endif // VK_USE_PLATFORM_WAYLAND_KHR
212 #ifdef VK_USE_PLATFORM_WIN32_KHR
213         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME) == 0) {
214 
215             my_data->instanceMap[instance].win32SurfaceExtensionEnabled = true;
216         }
217 #endif // VK_USE_PLATFORM_WIN32_KHR
218 #ifdef VK_USE_PLATFORM_XCB_KHR
219         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME) == 0) {
220 
221             my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = true;
222         }
223 #endif // VK_USE_PLATFORM_XCB_KHR
224 #ifdef VK_USE_PLATFORM_XLIB_KHR
225         if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME) == 0) {
226 
227             my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = true;
228         }
229 #endif // VK_USE_PLATFORM_XLIB_KHR
230     }
231 }
232 
233 #include "vk_dispatch_table_helper.h"
init_swapchain(layer_data * my_data,const VkAllocationCallbacks * pAllocator)234 static void init_swapchain(layer_data *my_data, const VkAllocationCallbacks *pAllocator) {
235 
236     layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_swapchain");
237 
238     if (!globalLockInitialized) {
239         loader_platform_thread_create_mutex(&globalLock);
240         globalLockInitialized = 1;
241     }
242 }
243 
surfaceTransformStr(VkSurfaceTransformFlagBitsKHR value)244 static const char *surfaceTransformStr(VkSurfaceTransformFlagBitsKHR value) {
245     // Return a string corresponding to the value:
246     return string_VkSurfaceTransformFlagBitsKHR(value);
247 }
248 
surfaceCompositeAlphaStr(VkCompositeAlphaFlagBitsKHR value)249 static const char *surfaceCompositeAlphaStr(VkCompositeAlphaFlagBitsKHR value) {
250     // Return a string corresponding to the value:
251     return string_VkCompositeAlphaFlagBitsKHR(value);
252 }
253 
presentModeStr(VkPresentModeKHR value)254 static const char *presentModeStr(VkPresentModeKHR value) {
255     // Return a string corresponding to the value:
256     return string_VkPresentModeKHR(value);
257 }
258 
sharingModeStr(VkSharingMode value)259 static const char *sharingModeStr(VkSharingMode value) {
260     // Return a string corresponding to the value:
261     return string_VkSharingMode(value);
262 }
263 
264 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkCreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)265 vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
266     VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
267 
268     assert(chain_info->u.pLayerInfo);
269     PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
270     PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
271     if (fpCreateInstance == NULL) {
272         return VK_ERROR_INITIALIZATION_FAILED;
273     }
274 
275     // Advance the link info for the next element on the chain
276     chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
277 
278     VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
279     if (result != VK_SUCCESS) {
280         return result;
281     }
282 
283     layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
284     my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
285     layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
286 
287     my_data->report_data = debug_report_create_instance(my_data->instance_dispatch_table, *pInstance,
288                                                         pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
289 
290     // Call the following function after my_data is initialized:
291     createInstanceRegisterExtensions(pCreateInfo, *pInstance);
292     init_swapchain(my_data, pAllocator);
293 
294     return result;
295 }
296 
vkDestroyInstance(VkInstance instance,const VkAllocationCallbacks * pAllocator)297 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
298     dispatch_key key = get_dispatch_key(instance);
299     layer_data *my_data = get_my_data_ptr(key, layer_data_map);
300     SwpInstance *pInstance = &(my_data->instanceMap[instance]);
301 
302     // Call down the call chain:
303     my_data->instance_dispatch_table->DestroyInstance(instance, pAllocator);
304 
305     loader_platform_thread_lock_mutex(&globalLock);
306 
307     // Do additional internal cleanup:
308     if (pInstance) {
309         // Delete all of the SwpPhysicalDevice's, SwpSurface's, and the
310         // SwpInstance associated with this instance:
311         for (auto it = pInstance->physicalDevices.begin(); it != pInstance->physicalDevices.end(); it++) {
312 
313             // Free memory that was allocated for/by this SwpPhysicalDevice:
314             SwpPhysicalDevice *pPhysicalDevice = it->second;
315             if (pPhysicalDevice) {
316                 if (pPhysicalDevice->pDevice) {
317                     LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
318                               "%s() called before all of its associated "
319                               "VkDevices were destroyed.",
320                               __FUNCTION__);
321                 }
322                 free(pPhysicalDevice->pSurfaceFormats);
323                 free(pPhysicalDevice->pPresentModes);
324             }
325 
326             // Erase the SwpPhysicalDevice's from the my_data->physicalDeviceMap (which
327             // are simply pointed to by the SwpInstance):
328             my_data->physicalDeviceMap.erase(it->second->physicalDevice);
329         }
330         for (auto it = pInstance->surfaces.begin(); it != pInstance->surfaces.end(); it++) {
331 
332             // Free memory that was allocated for/by this SwpPhysicalDevice:
333             SwpSurface *pSurface = it->second;
334             if (pSurface) {
335                 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
336                           "%s() called before all of its associated "
337                           "VkSurfaceKHRs were destroyed.",
338                           __FUNCTION__);
339             }
340         }
341         my_data->instanceMap.erase(instance);
342     }
343 
344     // Clean up logging callback, if any
345     while (my_data->logging_callback.size() > 0) {
346         VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
347         layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
348         my_data->logging_callback.pop_back();
349     }
350     layer_debug_report_destroy_instance(my_data->report_data);
351 
352     delete my_data->instance_dispatch_table;
353     layer_data_map.erase(key);
354     if (layer_data_map.empty()) {
355         // Release mutex when destroying last instance
356         loader_platform_thread_unlock_mutex(&globalLock);
357         loader_platform_thread_delete_mutex(&globalLock);
358         globalLockInitialized = 0;
359     } else {
360         loader_platform_thread_unlock_mutex(&globalLock);
361     }
362 }
363 
364 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,uint32_t * pQueueFamilyPropertyCount,VkQueueFamilyProperties * pQueueFamilyProperties)365 vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount,
366                                          VkQueueFamilyProperties *pQueueFamilyProperties) {
367     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
368 
369     // Call down the call chain:
370     my_data->instance_dispatch_table->GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount,
371                                                                              pQueueFamilyProperties);
372 
373     // Record the result of this query:
374     loader_platform_thread_lock_mutex(&globalLock);
375     SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
376     if (pPhysicalDevice && pQueueFamilyPropertyCount && !pQueueFamilyProperties) {
377         pPhysicalDevice->gotQueueFamilyPropertyCount = true;
378         pPhysicalDevice->numOfQueueFamilies = *pQueueFamilyPropertyCount;
379     }
380     loader_platform_thread_unlock_mutex(&globalLock);
381 }
382 
383 #ifdef VK_USE_PLATFORM_ANDROID_KHR
384 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkCreateAndroidSurfaceKHR(VkInstance instance,const VkAndroidSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)385 vkCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo,
386                           const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
387     VkResult result = VK_SUCCESS;
388     VkBool32 skipCall = VK_FALSE;
389     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
390     loader_platform_thread_lock_mutex(&globalLock);
391     SwpInstance *pInstance = &(my_data->instanceMap[instance]);
392 
393     // Validate that the platform extension was enabled:
394     if (pInstance && !pInstance->androidSurfaceExtensionEnabled) {
395         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
396                               "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
397                               VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
398     }
399 
400     if (!pCreateInfo) {
401         skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
402     } else {
403         if (pCreateInfo->sType != VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR) {
404             skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
405                                               "VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR");
406         }
407         if (pCreateInfo->pNext != NULL) {
408             skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
409         }
410     }
411 
412     if (VK_FALSE == skipCall) {
413         // Call down the call chain:
414         loader_platform_thread_unlock_mutex(&globalLock);
415         result = my_data->instance_dispatch_table->CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
416         loader_platform_thread_lock_mutex(&globalLock);
417 
418         // Obtain this pointer again after locking:
419         pInstance = &(my_data->instanceMap[instance]);
420         if ((result == VK_SUCCESS) && pInstance && pSurface) {
421             // Record the VkSurfaceKHR returned by the ICD:
422             my_data->surfaceMap[*pSurface].surface = *pSurface;
423             my_data->surfaceMap[*pSurface].pInstance = pInstance;
424             my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
425             my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
426             my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
427             // Point to the associated SwpInstance:
428             pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
429         }
430         loader_platform_thread_unlock_mutex(&globalLock);
431         return result;
432     }
433     loader_platform_thread_unlock_mutex(&globalLock);
434     return VK_ERROR_VALIDATION_FAILED_EXT;
435 }
436 #endif // VK_USE_PLATFORM_ANDROID_KHR
437 
438 #ifdef VK_USE_PLATFORM_MIR_KHR
439 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkCreateMirSurfaceKHR(VkInstance instance,const VkMirSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)440 vkCreateMirSurfaceKHR(VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
441                       VkSurfaceKHR *pSurface) {
442     VkResult result = VK_SUCCESS;
443     VkBool32 skipCall = VK_FALSE;
444     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
445     loader_platform_thread_lock_mutex(&globalLock);
446     SwpInstance *pInstance = &(my_data->instanceMap[instance]);
447 
448     // Validate that the platform extension was enabled:
449     if (pInstance && !pInstance->mirSurfaceExtensionEnabled) {
450         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
451                               "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
452                               VK_KHR_MIR_SURFACE_EXTENSION_NAME);
453     }
454 
455     if (!pCreateInfo) {
456         skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
457     } else {
458         if (pCreateInfo->sType != VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR) {
459             skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
460                                               "VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR");
461         }
462         if (pCreateInfo->pNext != NULL) {
463             skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
464         }
465     }
466 
467     if (VK_FALSE == skipCall) {
468         // Call down the call chain:
469         loader_platform_thread_unlock_mutex(&globalLock);
470         result = my_data->instance_dispatch_table->CreateMirSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
471         loader_platform_thread_lock_mutex(&globalLock);
472 
473         // Obtain this pointer again after locking:
474         pInstance = &(my_data->instanceMap[instance]);
475         if ((result == VK_SUCCESS) && pInstance && pSurface) {
476             // Record the VkSurfaceKHR returned by the ICD:
477             my_data->surfaceMap[*pSurface].surface = *pSurface;
478             my_data->surfaceMap[*pSurface].pInstance = pInstance;
479             my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
480             my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
481             my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
482             // Point to the associated SwpInstance:
483             pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
484         }
485         loader_platform_thread_unlock_mutex(&globalLock);
486         return result;
487     }
488     loader_platform_thread_unlock_mutex(&globalLock);
489     return VK_ERROR_VALIDATION_FAILED_EXT;
490 }
491 
vkGetPhysicalDeviceMirPresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,MirConnection * connection)492 VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceMirPresentationSupportKHR(VkPhysicalDevice physicalDevice,
493                                                                                             uint32_t queueFamilyIndex,
494                                                                                             MirConnection *connection) {
495     VkBool32 result = VK_FALSE;
496     VkBool32 skipCall = VK_FALSE;
497     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
498     loader_platform_thread_lock_mutex(&globalLock);
499     SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
500 
501     // Validate that the platform extension was enabled:
502     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->mirSurfaceExtensionEnabled) {
503         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
504                               SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
505                               "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
506                               VK_KHR_MIR_SURFACE_EXTENSION_NAME);
507     }
508     if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
509         skipCall |=
510             LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
511                                                    "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
512     }
513     loader_platform_thread_unlock_mutex(&globalLock);
514 
515     if (VK_FALSE == skipCall) {
516         // Call down the call chain:
517         result = my_data->instance_dispatch_table->GetPhysicalDeviceMirPresentationSupportKHR(physicalDevice, queueFamilyIndex,
518                                                                                               connection);
519     }
520     return result;
521 }
522 #endif // VK_USE_PLATFORM_MIR_KHR
523 
524 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
525 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkCreateWaylandSurfaceKHR(VkInstance instance,const VkWaylandSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)526 vkCreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
527                           const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
528     VkResult result = VK_SUCCESS;
529     VkBool32 skipCall = VK_FALSE;
530     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
531     loader_platform_thread_lock_mutex(&globalLock);
532     SwpInstance *pInstance = &(my_data->instanceMap[instance]);
533 
534     // Validate that the platform extension was enabled:
535     if (pInstance && !pInstance->waylandSurfaceExtensionEnabled) {
536         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
537                               "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
538                               VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
539     }
540 
541     if (!pCreateInfo) {
542         skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
543     } else {
544         if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR) {
545             skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
546                                               "VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR");
547         }
548         if (pCreateInfo->pNext != NULL) {
549             skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
550         }
551     }
552 
553     if (VK_FALSE == skipCall) {
554         // Call down the call chain:
555         loader_platform_thread_unlock_mutex(&globalLock);
556         result = my_data->instance_dispatch_table->CreateWaylandSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
557         loader_platform_thread_lock_mutex(&globalLock);
558 
559         // Obtain this pointer again after locking:
560         pInstance = &(my_data->instanceMap[instance]);
561         if ((result == VK_SUCCESS) && pInstance && pSurface) {
562             // Record the VkSurfaceKHR returned by the ICD:
563             my_data->surfaceMap[*pSurface].surface = *pSurface;
564             my_data->surfaceMap[*pSurface].pInstance = pInstance;
565             my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
566             my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
567             my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
568             // Point to the associated SwpInstance:
569             pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
570         }
571         loader_platform_thread_unlock_mutex(&globalLock);
572         return result;
573     }
574     loader_platform_thread_unlock_mutex(&globalLock);
575     return VK_ERROR_VALIDATION_FAILED_EXT;
576 }
577 
vkGetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,struct wl_display * display)578 VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,
579                                                                                                 uint32_t queueFamilyIndex,
580                                                                                                 struct wl_display *display) {
581     VkBool32 result = VK_FALSE;
582     VkBool32 skipCall = VK_FALSE;
583     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
584     loader_platform_thread_lock_mutex(&globalLock);
585     SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
586 
587     // Validate that the platform extension was enabled:
588     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->waylandSurfaceExtensionEnabled) {
589         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
590                               SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
591                               "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
592                               VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
593     }
594     if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
595         skipCall |=
596             LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
597                                                    "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
598     }
599     loader_platform_thread_unlock_mutex(&globalLock);
600 
601     if (VK_FALSE == skipCall) {
602         // Call down the call chain:
603         result = my_data->instance_dispatch_table->GetPhysicalDeviceWaylandPresentationSupportKHR(physicalDevice, queueFamilyIndex,
604                                                                                                   display);
605     }
606     return result;
607 }
608 #endif // VK_USE_PLATFORM_WAYLAND_KHR
609 
610 #ifdef VK_USE_PLATFORM_WIN32_KHR
611 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkCreateWin32SurfaceKHR(VkInstance instance,const VkWin32SurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)612 vkCreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
613                         const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
614     VkResult result = VK_SUCCESS;
615     VkBool32 skipCall = VK_FALSE;
616     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
617     loader_platform_thread_lock_mutex(&globalLock);
618     SwpInstance *pInstance = &(my_data->instanceMap[instance]);
619 
620     // Validate that the platform extension was enabled:
621     if (pInstance && !pInstance->win32SurfaceExtensionEnabled) {
622         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
623                               "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
624                               VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
625     }
626 
627     if (!pCreateInfo) {
628         skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
629     } else {
630         if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR) {
631             skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
632                                               "VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR");
633         }
634         if (pCreateInfo->pNext != NULL) {
635             skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
636         }
637     }
638 
639     if (VK_FALSE == skipCall) {
640         // Call down the call chain:
641         loader_platform_thread_unlock_mutex(&globalLock);
642         result = my_data->instance_dispatch_table->CreateWin32SurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
643         loader_platform_thread_lock_mutex(&globalLock);
644 
645         // Obtain this pointer again after locking:
646         pInstance = &(my_data->instanceMap[instance]);
647         if ((result == VK_SUCCESS) && pInstance && pSurface) {
648             // Record the VkSurfaceKHR returned by the ICD:
649             my_data->surfaceMap[*pSurface].surface = *pSurface;
650             my_data->surfaceMap[*pSurface].pInstance = pInstance;
651             my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
652             my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
653             my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
654             // Point to the associated SwpInstance:
655             pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
656         }
657         loader_platform_thread_unlock_mutex(&globalLock);
658         return result;
659     }
660     loader_platform_thread_unlock_mutex(&globalLock);
661     return VK_ERROR_VALIDATION_FAILED_EXT;
662 }
663 
664 VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL
vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex)665 vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex) {
666     VkBool32 result = VK_FALSE;
667     VkBool32 skipCall = VK_FALSE;
668     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
669     loader_platform_thread_lock_mutex(&globalLock);
670     SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
671 
672     // Validate that the platform extension was enabled:
673     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->win32SurfaceExtensionEnabled) {
674         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
675                               SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
676                               "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
677                               VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
678     }
679     if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
680         skipCall |=
681             LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
682                                                    "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
683     }
684     loader_platform_thread_unlock_mutex(&globalLock);
685 
686     if (VK_FALSE == skipCall) {
687         // Call down the call chain:
688         result = my_data->instance_dispatch_table->GetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
689     }
690     return result;
691 }
692 #endif // VK_USE_PLATFORM_WIN32_KHR
693 
694 #ifdef VK_USE_PLATFORM_XCB_KHR
695 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkCreateXcbSurfaceKHR(VkInstance instance,const VkXcbSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)696 vkCreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
697                       VkSurfaceKHR *pSurface) {
698     VkResult result = VK_SUCCESS;
699     VkBool32 skipCall = VK_FALSE;
700     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
701     loader_platform_thread_lock_mutex(&globalLock);
702     SwpInstance *pInstance = &(my_data->instanceMap[instance]);
703 
704     // Validate that the platform extension was enabled:
705     if (pInstance && !pInstance->xcbSurfaceExtensionEnabled) {
706         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
707                               "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
708                               VK_KHR_XCB_SURFACE_EXTENSION_NAME);
709     }
710 
711     if (!pCreateInfo) {
712         skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
713     } else {
714         if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR) {
715             skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
716                                               "VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR");
717         }
718         if (pCreateInfo->pNext != NULL) {
719             skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
720         }
721     }
722 
723     if (VK_FALSE == skipCall) {
724         // Call down the call chain:
725         loader_platform_thread_unlock_mutex(&globalLock);
726         result = my_data->instance_dispatch_table->CreateXcbSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
727         loader_platform_thread_lock_mutex(&globalLock);
728 
729         // Obtain this pointer again after locking:
730         pInstance = &(my_data->instanceMap[instance]);
731         if ((result == VK_SUCCESS) && pInstance && pSurface) {
732             // Record the VkSurfaceKHR returned by the ICD:
733             my_data->surfaceMap[*pSurface].surface = *pSurface;
734             my_data->surfaceMap[*pSurface].pInstance = pInstance;
735             my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
736             my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
737             my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
738             // Point to the associated SwpInstance:
739             pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
740         }
741         loader_platform_thread_unlock_mutex(&globalLock);
742         return result;
743     }
744     loader_platform_thread_unlock_mutex(&globalLock);
745     return VK_ERROR_VALIDATION_FAILED_EXT;
746 }
747 
748 VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL
vkGetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,xcb_connection_t * connection,xcb_visualid_t visual_id)749 vkGetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex,
750                                              xcb_connection_t *connection, xcb_visualid_t visual_id) {
751     VkBool32 result = VK_FALSE;
752     VkBool32 skipCall = VK_FALSE;
753     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
754     loader_platform_thread_lock_mutex(&globalLock);
755     SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
756 
757     // Validate that the platform extension was enabled:
758     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->xcbSurfaceExtensionEnabled) {
759         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
760                               SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
761                               "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
762                               VK_KHR_XCB_SURFACE_EXTENSION_NAME);
763     }
764     if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
765         skipCall |=
766             LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
767                                                    "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
768     }
769     loader_platform_thread_unlock_mutex(&globalLock);
770 
771     if (VK_FALSE == skipCall) {
772         // Call down the call chain:
773         result = my_data->instance_dispatch_table->GetPhysicalDeviceXcbPresentationSupportKHR(physicalDevice, queueFamilyIndex,
774                                                                                               connection, visual_id);
775     }
776     return result;
777 }
778 #endif // VK_USE_PLATFORM_XCB_KHR
779 
780 #ifdef VK_USE_PLATFORM_XLIB_KHR
781 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkCreateXlibSurfaceKHR(VkInstance instance,const VkXlibSurfaceCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSurfaceKHR * pSurface)782 vkCreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
783                        VkSurfaceKHR *pSurface) {
784     VkResult result = VK_SUCCESS;
785     VkBool32 skipCall = VK_FALSE;
786     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
787     loader_platform_thread_lock_mutex(&globalLock);
788     SwpInstance *pInstance = &(my_data->instanceMap[instance]);
789 
790     // Validate that the platform extension was enabled:
791     if (pInstance && !pInstance->xlibSurfaceExtensionEnabled) {
792         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
793                               "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
794                               VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
795     }
796 
797     if (!pCreateInfo) {
798         skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
799     } else {
800         if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR) {
801             skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
802                                               "VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR");
803         }
804         if (pCreateInfo->pNext != NULL) {
805             skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
806         }
807     }
808 
809     if (VK_FALSE == skipCall) {
810         // Call down the call chain:
811         loader_platform_thread_unlock_mutex(&globalLock);
812         result = my_data->instance_dispatch_table->CreateXlibSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
813         loader_platform_thread_lock_mutex(&globalLock);
814 
815         // Obtain this pointer again after locking:
816         pInstance = &(my_data->instanceMap[instance]);
817         if ((result == VK_SUCCESS) && pInstance && pSurface) {
818             // Record the VkSurfaceKHR returned by the ICD:
819             my_data->surfaceMap[*pSurface].surface = *pSurface;
820             my_data->surfaceMap[*pSurface].pInstance = pInstance;
821             my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
822             my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
823             my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
824             // Point to the associated SwpInstance:
825             pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
826         }
827         loader_platform_thread_unlock_mutex(&globalLock);
828         return result;
829     }
830     loader_platform_thread_unlock_mutex(&globalLock);
831     return VK_ERROR_VALIDATION_FAILED_EXT;
832 }
833 
vkGetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,Display * dpy,VisualID visualID)834 VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
835                                                                                              uint32_t queueFamilyIndex,
836                                                                                              Display *dpy, VisualID visualID) {
837     VkBool32 result = VK_FALSE;
838     VkBool32 skipCall = VK_FALSE;
839     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
840     loader_platform_thread_lock_mutex(&globalLock);
841     SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
842 
843     // Validate that the platform extension was enabled:
844     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->xlibSurfaceExtensionEnabled) {
845         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
846                               SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
847                               "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
848                               VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
849     }
850     if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
851         skipCall |=
852             LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
853                                                    "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
854     }
855     loader_platform_thread_unlock_mutex(&globalLock);
856 
857     if (VK_FALSE == skipCall) {
858         // Call down the call chain:
859         result = my_data->instance_dispatch_table->GetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex,
860                                                                                                dpy, visualID);
861     }
862     return result;
863 }
864 #endif // VK_USE_PLATFORM_XLIB_KHR
865 
866 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
vkDestroySurfaceKHR(VkInstance instance,VkSurfaceKHR surface,const VkAllocationCallbacks * pAllocator)867 vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) {
868     VkBool32 skipCall = VK_FALSE;
869     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
870     loader_platform_thread_lock_mutex(&globalLock);
871     SwpSurface *pSurface = &my_data->surfaceMap[surface];
872 
873     // Regardless of skipCall value, do some internal cleanup:
874     if (pSurface) {
875         // Delete the SwpSurface associated with this surface:
876         if (pSurface->pInstance) {
877             pSurface->pInstance->surfaces.erase(surface);
878         }
879         if (!pSurface->swapchains.empty()) {
880             LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
881                       "%s() called before all of its associated "
882                       "VkSwapchainKHRs were destroyed.",
883                       __FUNCTION__);
884             // Empty and then delete all SwpSwapchain's
885             for (auto it = pSurface->swapchains.begin(); it != pSurface->swapchains.end(); it++) {
886                 // Delete all SwpImage's
887                 it->second->images.clear();
888                 // In case the swapchain's device hasn't been destroyed yet
889                 // (which isn't likely, but is possible), delete its
890                 // association with this swapchain (i.e. so we can't point to
891                 // this swpchain from that device, later on):
892                 if (it->second->pDevice) {
893                     it->second->pDevice->swapchains.clear();
894                 }
895             }
896             pSurface->swapchains.clear();
897         }
898         if ((pAllocator != NULL) != pSurface->usedAllocatorToCreate) {
899             LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
900                       "%s() called with incompatible pAllocator from when "
901                       "the object was created.",
902                       __FUNCTION__);
903         }
904         my_data->surfaceMap.erase(surface);
905     }
906     loader_platform_thread_unlock_mutex(&globalLock);
907 
908     if (VK_FALSE == skipCall) {
909         // Call down the call chain:
910         my_data->instance_dispatch_table->DestroySurfaceKHR(instance, surface, pAllocator);
911     }
912 }
913 
914 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkEnumeratePhysicalDevices(VkInstance instance,uint32_t * pPhysicalDeviceCount,VkPhysicalDevice * pPhysicalDevices)915 vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) {
916     VkResult result = VK_SUCCESS;
917     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
918 
919     // Call down the call chain:
920     result = my_data->instance_dispatch_table->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
921 
922     loader_platform_thread_lock_mutex(&globalLock);
923     SwpInstance *pInstance = &(my_data->instanceMap[instance]);
924     if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices && (*pPhysicalDeviceCount > 0)) {
925         // Record the VkPhysicalDevices returned by the ICD:
926         for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
927             my_data->physicalDeviceMap[pPhysicalDevices[i]].physicalDevice = pPhysicalDevices[i];
928             my_data->physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance;
929             my_data->physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL;
930             my_data->physicalDeviceMap[pPhysicalDevices[i]].gotQueueFamilyPropertyCount = false;
931             my_data->physicalDeviceMap[pPhysicalDevices[i]].gotSurfaceCapabilities = false;
932             my_data->physicalDeviceMap[pPhysicalDevices[i]].surfaceFormatCount = 0;
933             my_data->physicalDeviceMap[pPhysicalDevices[i]].pSurfaceFormats = NULL;
934             my_data->physicalDeviceMap[pPhysicalDevices[i]].presentModeCount = 0;
935             my_data->physicalDeviceMap[pPhysicalDevices[i]].pPresentModes = NULL;
936             // Point to the associated SwpInstance:
937             if (pInstance) {
938                 pInstance->physicalDevices[pPhysicalDevices[i]] = &my_data->physicalDeviceMap[pPhysicalDevices[i]];
939             }
940         }
941     }
942     loader_platform_thread_unlock_mutex(&globalLock);
943     return result;
944 }
945 
vkCreateDevice(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice)946 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice,
947                                                               const VkDeviceCreateInfo *pCreateInfo,
948                                                               const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
949     VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
950 
951     assert(chain_info->u.pLayerInfo);
952     PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
953     PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
954     PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice");
955     if (fpCreateDevice == NULL) {
956         return VK_ERROR_INITIALIZATION_FAILED;
957     }
958 
959     // Advance the link info for the next element on the chain
960     chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
961 
962     VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
963     if (result != VK_SUCCESS) {
964         return result;
965     }
966 
967     loader_platform_thread_lock_mutex(&globalLock);
968     layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
969     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
970 
971     // Setup device dispatch table
972     my_device_data->device_dispatch_table = new VkLayerDispatchTable;
973     layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
974 
975     my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
976     createDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice);
977     loader_platform_thread_unlock_mutex(&globalLock);
978 
979     return result;
980 }
981 
vkDestroyDevice(VkDevice device,const VkAllocationCallbacks * pAllocator)982 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
983     dispatch_key key = get_dispatch_key(device);
984     layer_data *my_data = get_my_data_ptr(key, layer_data_map);
985 
986     // Call down the call chain:
987     my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
988 
989     // Do some internal cleanup:
990     loader_platform_thread_lock_mutex(&globalLock);
991     SwpDevice *pDevice = &my_data->deviceMap[device];
992     if (pDevice) {
993         // Delete the SwpDevice associated with this device:
994         if (pDevice->pPhysicalDevice) {
995             pDevice->pPhysicalDevice->pDevice = NULL;
996         }
997         if (!pDevice->swapchains.empty()) {
998             LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
999                       "%s() called before all of its associated "
1000                       "VkSwapchainKHRs were destroyed.",
1001                       __FUNCTION__);
1002             // Empty and then delete all SwpSwapchain's
1003             for (auto it = pDevice->swapchains.begin(); it != pDevice->swapchains.end(); it++) {
1004                 // Delete all SwpImage's
1005                 it->second->images.clear();
1006                 // In case the swapchain's surface hasn't been destroyed yet
1007                 // (which is likely) delete its association with this swapchain
1008                 // (i.e. so we can't point to this swpchain from that surface,
1009                 // later on):
1010                 if (it->second->pSurface) {
1011                     it->second->pSurface->swapchains.clear();
1012                 }
1013             }
1014             pDevice->swapchains.clear();
1015         }
1016         my_data->deviceMap.erase(device);
1017     }
1018     delete my_data->device_dispatch_table;
1019     layer_data_map.erase(key);
1020     loader_platform_thread_unlock_mutex(&globalLock);
1021 }
1022 
vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,VkSurfaceKHR surface,VkBool32 * pSupported)1023 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
1024                                                                                     uint32_t queueFamilyIndex, VkSurfaceKHR surface,
1025                                                                                     VkBool32 *pSupported) {
1026     VkResult result = VK_SUCCESS;
1027     VkBool32 skipCall = VK_FALSE;
1028     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1029     loader_platform_thread_lock_mutex(&globalLock);
1030     SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
1031 
1032     // Validate that the surface extension was enabled:
1033     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1034         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1035                               SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1036                               "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1037                               VK_KHR_SURFACE_EXTENSION_NAME);
1038     }
1039     if (!pPhysicalDevice->gotQueueFamilyPropertyCount) {
1040         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, "VkPhysicalDevice",
1041                               SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES, "%s() called before calling the "
1042                                                                       "vkGetPhysicalDeviceQueueFamilyProperties "
1043                                                                       "function.",
1044                               __FUNCTION__);
1045     } else if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
1046         skipCall |=
1047             LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
1048                                                    "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
1049     }
1050     if (!pSupported) {
1051         skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSupported");
1052     }
1053 
1054     if (VK_FALSE == skipCall) {
1055         // Call down the call chain:
1056         loader_platform_thread_unlock_mutex(&globalLock);
1057         result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface,
1058                                                                                       pSupported);
1059         loader_platform_thread_lock_mutex(&globalLock);
1060 
1061         // Obtain this pointer again after locking:
1062         pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
1063         if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
1064             // Record the result of this query:
1065             SwpInstance *pInstance = pPhysicalDevice->pInstance;
1066             SwpSurface *pSurface = (pInstance) ? pInstance->surfaces[surface] : NULL;
1067             if (pSurface) {
1068                 pPhysicalDevice->supportedSurfaces[surface] = pSurface;
1069                 if (!pSurface->numQueueFamilyIndexSupport) {
1070                     if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
1071                         pSurface->pQueueFamilyIndexSupport =
1072                             (VkBool32 *)malloc(pPhysicalDevice->numOfQueueFamilies * sizeof(VkBool32));
1073                         if (pSurface->pQueueFamilyIndexSupport != NULL) {
1074                             pSurface->numQueueFamilyIndexSupport = pPhysicalDevice->numOfQueueFamilies;
1075                         }
1076                     }
1077                 }
1078                 if (pSurface->numQueueFamilyIndexSupport) {
1079                     pSurface->pQueueFamilyIndexSupport[queueFamilyIndex] = *pSupported;
1080                 }
1081             }
1082         }
1083         loader_platform_thread_unlock_mutex(&globalLock);
1084         return result;
1085     }
1086     loader_platform_thread_unlock_mutex(&globalLock);
1087     return VK_ERROR_VALIDATION_FAILED_EXT;
1088 }
1089 
1090 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,VkSurfaceCapabilitiesKHR * pSurfaceCapabilities)1091 vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
1092                                           VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) {
1093     VkResult result = VK_SUCCESS;
1094     VkBool32 skipCall = VK_FALSE;
1095     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1096     loader_platform_thread_lock_mutex(&globalLock);
1097     SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
1098 
1099     // Validate that the surface extension was enabled:
1100     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1101         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1102                               SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1103                               "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1104                               VK_KHR_SURFACE_EXTENSION_NAME);
1105     }
1106     if (!pSurfaceCapabilities) {
1107         skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceCapabilities");
1108     }
1109 
1110     if (VK_FALSE == skipCall) {
1111         // Call down the call chain:
1112         loader_platform_thread_unlock_mutex(&globalLock);
1113         result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface,
1114                                                                                            pSurfaceCapabilities);
1115         loader_platform_thread_lock_mutex(&globalLock);
1116 
1117         // Obtain this pointer again after locking:
1118         pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
1119         if ((result == VK_SUCCESS) && pPhysicalDevice) {
1120             // Record the result of this query:
1121             pPhysicalDevice->gotSurfaceCapabilities = true;
1122             // FIXME: NEED TO COPY THIS DATA, BECAUSE pSurfaceCapabilities POINTS TO APP-ALLOCATED DATA
1123             pPhysicalDevice->surfaceCapabilities = *pSurfaceCapabilities;
1124         }
1125         loader_platform_thread_unlock_mutex(&globalLock);
1126         return result;
1127     }
1128     loader_platform_thread_unlock_mutex(&globalLock);
1129     return VK_ERROR_VALIDATION_FAILED_EXT;
1130 }
1131 
1132 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,uint32_t * pSurfaceFormatCount,VkSurfaceFormatKHR * pSurfaceFormats)1133 vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount,
1134                                      VkSurfaceFormatKHR *pSurfaceFormats) {
1135     VkResult result = VK_SUCCESS;
1136     VkBool32 skipCall = VK_FALSE;
1137     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1138     loader_platform_thread_lock_mutex(&globalLock);
1139     SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
1140 
1141     // Validate that the surface extension was enabled:
1142     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1143         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1144                               SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1145                               "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1146                               VK_KHR_SURFACE_EXTENSION_NAME);
1147     }
1148     if (!pSurfaceFormatCount) {
1149         skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceFormatCount");
1150     }
1151 
1152     if (VK_FALSE == skipCall) {
1153         // Call down the call chain:
1154         loader_platform_thread_unlock_mutex(&globalLock);
1155         result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount,
1156                                                                                       pSurfaceFormats);
1157         loader_platform_thread_lock_mutex(&globalLock);
1158 
1159         // Obtain this pointer again after locking:
1160         pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
1161         if ((result == VK_SUCCESS) && pPhysicalDevice && !pSurfaceFormats && pSurfaceFormatCount) {
1162             // Record the result of this preliminary query:
1163             pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
1164         } else if ((result == VK_SUCCESS) && pPhysicalDevice && pSurfaceFormats && pSurfaceFormatCount) {
1165             // Compare the preliminary value of *pSurfaceFormatCount with the
1166             // value this time:
1167             if (*pSurfaceFormatCount > pPhysicalDevice->surfaceFormatCount) {
1168                 LOG_ERROR_INVALID_COUNT(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceFormatCount",
1169                                         "pSurfaceFormats", *pSurfaceFormatCount, pPhysicalDevice->surfaceFormatCount);
1170             } else if (*pSurfaceFormatCount > 0) {
1171                 // Record the result of this query:
1172                 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
1173                 pPhysicalDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)malloc(*pSurfaceFormatCount * sizeof(VkSurfaceFormatKHR));
1174                 if (pPhysicalDevice->pSurfaceFormats) {
1175                     for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) {
1176                         pPhysicalDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
1177                     }
1178                 } else {
1179                     pPhysicalDevice->surfaceFormatCount = 0;
1180                 }
1181             }
1182         }
1183         loader_platform_thread_unlock_mutex(&globalLock);
1184         return result;
1185     }
1186     loader_platform_thread_unlock_mutex(&globalLock);
1187     return VK_ERROR_VALIDATION_FAILED_EXT;
1188 }
1189 
1190 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,uint32_t * pPresentModeCount,VkPresentModeKHR * pPresentModes)1191 vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pPresentModeCount,
1192                                           VkPresentModeKHR *pPresentModes) {
1193     VkResult result = VK_SUCCESS;
1194     VkBool32 skipCall = VK_FALSE;
1195     layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1196     loader_platform_thread_lock_mutex(&globalLock);
1197     SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
1198 
1199     // Validate that the surface extension was enabled:
1200     if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1201         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1202                               SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1203                               "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1204                               VK_KHR_SURFACE_EXTENSION_NAME);
1205     }
1206     if (!pPresentModeCount) {
1207         skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pPresentModeCount");
1208     }
1209 
1210     if (VK_FALSE == skipCall) {
1211         // Call down the call chain:
1212         loader_platform_thread_unlock_mutex(&globalLock);
1213         result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface,
1214                                                                                            pPresentModeCount, pPresentModes);
1215         loader_platform_thread_lock_mutex(&globalLock);
1216 
1217         // Obtain this pointer again after locking:
1218         pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
1219         if ((result == VK_SUCCESS) && pPhysicalDevice && !pPresentModes && pPresentModeCount) {
1220             // Record the result of this preliminary query:
1221             pPhysicalDevice->presentModeCount = *pPresentModeCount;
1222         } else if ((result == VK_SUCCESS) && pPhysicalDevice && pPresentModes && pPresentModeCount) {
1223             // Compare the preliminary value of *pPresentModeCount with the
1224             // value this time:
1225             if (*pPresentModeCount > pPhysicalDevice->presentModeCount) {
1226                 LOG_ERROR_INVALID_COUNT(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pPresentModeCount",
1227                                         "pPresentModes", *pPresentModeCount, pPhysicalDevice->presentModeCount);
1228             } else if (*pPresentModeCount > 0) {
1229                 // Record the result of this query:
1230                 pPhysicalDevice->presentModeCount = *pPresentModeCount;
1231                 pPhysicalDevice->pPresentModes = (VkPresentModeKHR *)malloc(*pPresentModeCount * sizeof(VkPresentModeKHR));
1232                 if (pPhysicalDevice->pPresentModes) {
1233                     for (uint32_t i = 0; i < *pPresentModeCount; i++) {
1234                         pPhysicalDevice->pPresentModes[i] = pPresentModes[i];
1235                     }
1236                 } else {
1237                     pPhysicalDevice->presentModeCount = 0;
1238                 }
1239             }
1240         }
1241         loader_platform_thread_unlock_mutex(&globalLock);
1242         return result;
1243     }
1244     loader_platform_thread_unlock_mutex(&globalLock);
1245     return VK_ERROR_VALIDATION_FAILED_EXT;
1246 }
1247 
1248 // This function does the up-front validation work for vkCreateSwapchainKHR(),
1249 // and returns VK_TRUE if a logging callback indicates that the call down the
1250 // chain should be skipped:
validateCreateSwapchainKHR(VkDevice device,const VkSwapchainCreateInfoKHR * pCreateInfo,VkSwapchainKHR * pSwapchain)1251 static VkBool32 validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
1252                                            VkSwapchainKHR *pSwapchain) {
1253     // TODO: Validate cases of re-creating a swapchain (the current code
1254     // assumes a new swapchain is being created).
1255     VkBool32 skipCall = VK_FALSE;
1256     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1257     char fn[] = "vkCreateSwapchainKHR";
1258     SwpDevice *pDevice = &my_data->deviceMap[device];
1259 
1260     // Validate that the swapchain extension was enabled:
1261     if (pDevice && !pDevice->swapchainExtensionEnabled) {
1262         return LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1263                          "%s() called even though the %s extension was not enabled for this VkDevice.", fn,
1264                          VK_KHR_SWAPCHAIN_EXTENSION_NAME);
1265     }
1266     if (!pCreateInfo) {
1267         skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
1268     } else {
1269         if (pCreateInfo->sType != VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR) {
1270             skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
1271                                               "VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR");
1272         }
1273         if (pCreateInfo->pNext != NULL) {
1274             skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
1275         }
1276     }
1277     if (!pSwapchain) {
1278         skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchain");
1279     }
1280 
1281     // Keep around a useful pointer to pPhysicalDevice:
1282     SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
1283 
1284     // Validate pCreateInfo values with result of
1285     // vkGetPhysicalDeviceQueueFamilyProperties
1286     if (pPhysicalDevice && pPhysicalDevice->gotQueueFamilyPropertyCount) {
1287         for (auto i = 0; i < pCreateInfo->queueFamilyIndexCount; i++) {
1288             if (pCreateInfo->pQueueFamilyIndices[i] >= pPhysicalDevice->numOfQueueFamilies) {
1289                 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
1290                                                                    "VkPhysicalDevice", pCreateInfo->pQueueFamilyIndices[i],
1291                                                                    pPhysicalDevice->numOfQueueFamilies);
1292             }
1293         }
1294     }
1295 
1296     // Validate pCreateInfo values with the results of
1297     // vkGetPhysicalDeviceSurfaceCapabilitiesKHR():
1298     if (!pPhysicalDevice || !pPhysicalDevice->gotSurfaceCapabilities) {
1299         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
1300                               "%s() called before calling "
1301                               "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1302                               fn);
1303     } else if (pCreateInfo) {
1304         // Validate pCreateInfo->surface to make sure that
1305         // vkGetPhysicalDeviceSurfaceSupportKHR() reported this as a supported
1306         // surface:
1307         SwpSurface *pSurface = ((pPhysicalDevice) ? pPhysicalDevice->supportedSurfaces[pCreateInfo->surface] : NULL);
1308         if (!pSurface) {
1309             skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE,
1310                                   "%s() called with pCreateInfo->surface that "
1311                                   "was not returned by "
1312                                   "vkGetPhysicalDeviceSurfaceSupportKHR() "
1313                                   "for the device.",
1314                                   fn);
1315         }
1316 
1317         // Validate pCreateInfo->minImageCount against
1318         // VkSurfaceCapabilitiesKHR::{min|max}ImageCount:
1319         VkSurfaceCapabilitiesKHR *pCapabilities = &pPhysicalDevice->surfaceCapabilities;
1320         if ((pCreateInfo->minImageCount < pCapabilities->minImageCount) ||
1321             ((pCapabilities->maxImageCount > 0) && (pCreateInfo->minImageCount > pCapabilities->maxImageCount))) {
1322             skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1323                                   SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT, "%s() called with pCreateInfo->minImageCount "
1324                                                                            "= %d, which is outside the bounds returned "
1325                                                                            "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. "
1326                                                                            "minImageCount = %d, maxImageCount = %d).",
1327                                   fn, pCreateInfo->minImageCount, pCapabilities->minImageCount, pCapabilities->maxImageCount);
1328         }
1329         // Validate pCreateInfo->imageExtent against
1330         // VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
1331         if ((pCapabilities->currentExtent.width == -1) &&
1332             ((pCreateInfo->imageExtent.width < pCapabilities->minImageExtent.width) ||
1333              (pCreateInfo->imageExtent.width > pCapabilities->maxImageExtent.width) ||
1334              (pCreateInfo->imageExtent.height < pCapabilities->minImageExtent.height) ||
1335              (pCreateInfo->imageExtent.height > pCapabilities->maxImageExtent.height))) {
1336             skipCall |= LOG_ERROR(
1337                 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS,
1338                 "%s() called with pCreateInfo->imageExtent = "
1339                 "(%d,%d), which is outside the bounds "
1340                 "returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): "
1341                 "currentExtent = (%d,%d), minImageExtent = "
1342                 "(%d,%d), maxImageExtent = (%d,%d).",
1343                 fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, pCapabilities->currentExtent.width,
1344                 pCapabilities->currentExtent.height, pCapabilities->minImageExtent.width, pCapabilities->minImageExtent.height,
1345                 pCapabilities->maxImageExtent.width, pCapabilities->maxImageExtent.height);
1346         }
1347         if ((pCapabilities->currentExtent.width != -1) &&
1348             ((pCreateInfo->imageExtent.width != pCapabilities->currentExtent.width) ||
1349              (pCreateInfo->imageExtent.height != pCapabilities->currentExtent.height))) {
1350             skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1351                                   SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN, "%s() called with pCreateInfo->imageExtent = "
1352                                                                               "(%d,%d), which is not equal to the "
1353                                                                               "currentExtent = (%d,%d) returned by "
1354                                                                               "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1355                                   fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height,
1356                                   pCapabilities->currentExtent.width, pCapabilities->currentExtent.height);
1357         }
1358         // Validate pCreateInfo->preTransform has one bit set (1st two
1359         // lines of if-statement), which bit is also set in
1360         // VkSurfaceCapabilitiesKHR::supportedTransforms (3rd line of if-statement):
1361         if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) ||
1362             !(pCreateInfo->preTransform & pCapabilities->supportedTransforms)) {
1363             // This is an error situation; one for which we'd like to give
1364             // the developer a helpful, multi-line error message.  Build it
1365             // up a little at a time, and then log it:
1366             std::string errorString = "";
1367             char str[1024];
1368             // Here's the first part of the message:
1369             sprintf(str, "%s() called with a non-supported "
1370                          "pCreateInfo->preTransform (i.e. %s).  "
1371                          "Supported values are:\n",
1372                     fn, surfaceTransformStr(pCreateInfo->preTransform));
1373             errorString += str;
1374             for (int i = 0; i < 32; i++) {
1375                 // Build up the rest of the message:
1376                 if ((1 << i) & pCapabilities->supportedTransforms) {
1377                     const char *newStr = surfaceTransformStr((VkSurfaceTransformFlagBitsKHR)(1 << i));
1378                     sprintf(str, "    %s\n", newStr);
1379                     errorString += str;
1380                 }
1381             }
1382             // Log the message that we've built up:
1383             skipCall |= debug_report_log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1384                                              VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, (uint64_t)device, __LINE__,
1385                                              SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM, LAYER_NAME, errorString.c_str());
1386         }
1387         // Validate pCreateInfo->compositeAlpha has one bit set (1st two
1388         // lines of if-statement), which bit is also set in
1389         // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha (3rd line of if-statement):
1390         if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) ||
1391             !((pCreateInfo->compositeAlpha) & pCapabilities->supportedCompositeAlpha)) {
1392             // This is an error situation; one for which we'd like to give
1393             // the developer a helpful, multi-line error message.  Build it
1394             // up a little at a time, and then log it:
1395             std::string errorString = "";
1396             char str[1024];
1397             // Here's the first part of the message:
1398             sprintf(str, "%s() called with a non-supported "
1399                          "pCreateInfo->compositeAlpha (i.e. %s).  "
1400                          "Supported values are:\n",
1401                     fn, surfaceCompositeAlphaStr(pCreateInfo->compositeAlpha));
1402             errorString += str;
1403             for (int i = 0; i < 32; i++) {
1404                 // Build up the rest of the message:
1405                 if ((1 << i) & pCapabilities->supportedCompositeAlpha) {
1406                     const char *newStr = surfaceCompositeAlphaStr((VkCompositeAlphaFlagBitsKHR)(1 << i));
1407                     sprintf(str, "    %s\n", newStr);
1408                     errorString += str;
1409                 }
1410             }
1411             // Log the message that we've built up:
1412             skipCall |= debug_report_log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
1413                                              VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, (uint64_t)device, 0,
1414                                              SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA, LAYER_NAME, errorString.c_str());
1415         }
1416         // Validate pCreateInfo->imageArraySize against
1417         // VkSurfaceCapabilitiesKHR::maxImageArraySize:
1418         if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > pCapabilities->maxImageArrayLayers)) {
1419             skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1420                                   SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_SIZE, "%s() called with a non-supported "
1421                                                                             "pCreateInfo->imageArraySize (i.e. %d).  "
1422                                                                             "Minimum value is 1, maximum value is %d.",
1423                                   fn, pCreateInfo->imageArrayLayers, pCapabilities->maxImageArrayLayers);
1424         }
1425         // Validate pCreateInfo->imageUsage against
1426         // VkSurfaceCapabilitiesKHR::supportedUsageFlags:
1427         if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & pCapabilities->supportedUsageFlags)) {
1428             skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1429                                   SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS, "%s() called with a non-supported "
1430                                                                              "pCreateInfo->imageUsage (i.e. 0x%08x)."
1431                                                                              "  Supported flag bits are 0x%08x.",
1432                                   fn, pCreateInfo->imageUsage, pCapabilities->supportedUsageFlags);
1433         }
1434     }
1435 
1436     // Validate pCreateInfo values with the results of
1437     // vkGetPhysicalDeviceSurfaceFormatsKHR():
1438     if (!pPhysicalDevice || !pPhysicalDevice->surfaceFormatCount) {
1439         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
1440                               "%s() called before calling "
1441                               "vkGetPhysicalDeviceSurfaceFormatsKHR().",
1442                               fn);
1443     } else if (pCreateInfo) {
1444         // Validate pCreateInfo->imageFormat against
1445         // VkSurfaceFormatKHR::format:
1446         bool foundFormat = false;
1447         bool foundColorSpace = false;
1448         bool foundMatch = false;
1449         for (uint32_t i = 0; i < pPhysicalDevice->surfaceFormatCount; i++) {
1450             if (pCreateInfo->imageFormat == pPhysicalDevice->pSurfaceFormats[i].format) {
1451                 // Validate pCreateInfo->imageColorSpace against
1452                 // VkSurfaceFormatKHR::colorSpace:
1453                 foundFormat = true;
1454                 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1455                     foundMatch = true;
1456                     break;
1457                 }
1458             } else {
1459                 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1460                     foundColorSpace = true;
1461                 }
1462             }
1463         }
1464         if (!foundMatch) {
1465             if (!foundFormat) {
1466                 if (!foundColorSpace) {
1467                     skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1468                                           SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP, "%s() called with neither a "
1469                                                                                     "supported pCreateInfo->imageFormat "
1470                                                                                     "(i.e. %d) nor a supported "
1471                                                                                     "pCreateInfo->imageColorSpace "
1472                                                                                     "(i.e. %d).",
1473                                           fn, pCreateInfo->imageFormat, pCreateInfo->imageColorSpace);
1474                 } else {
1475                     skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1476                                           SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT, "%s() called with a non-supported "
1477                                                                                 "pCreateInfo->imageFormat (i.e. %d).",
1478                                           fn, pCreateInfo->imageFormat);
1479                 }
1480             } else if (!foundColorSpace) {
1481                 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1482                                       SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE, "%s() called with a non-supported "
1483                                                                                  "pCreateInfo->imageColorSpace (i.e. %d).",
1484                                       fn, pCreateInfo->imageColorSpace);
1485             }
1486         }
1487     }
1488 
1489     // Validate pCreateInfo values with the results of
1490     // vkGetPhysicalDeviceSurfacePresentModesKHR():
1491     if (!pPhysicalDevice || !pPhysicalDevice->presentModeCount) {
1492         if (!pCreateInfo || (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR)) {
1493             skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
1494                                   "%s() called before calling "
1495                                   "vkGetPhysicalDeviceSurfacePresentModesKHR().",
1496                                   fn);
1497         }
1498     } else if (pCreateInfo) {
1499         // Validate pCreateInfo->presentMode against
1500         // vkGetPhysicalDeviceSurfacePresentModesKHR():
1501         bool foundMatch = false;
1502         for (uint32_t i = 0; i < pPhysicalDevice->presentModeCount; i++) {
1503             if (pPhysicalDevice->pPresentModes[i] == pCreateInfo->presentMode) {
1504                 foundMatch = true;
1505                 break;
1506             }
1507         }
1508         if (!foundMatch) {
1509             skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1510                                   SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE, "%s() called with a non-supported "
1511                                                                           "pCreateInfo->presentMode (i.e. %s).",
1512                                   fn, presentModeStr(pCreateInfo->presentMode));
1513         }
1514     }
1515 
1516     // Validate pCreateInfo->imageSharingMode and related values:
1517     if (pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT) {
1518         if ((pCreateInfo->queueFamilyIndexCount <= 1) || !pCreateInfo->pQueueFamilyIndices) {
1519             skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1520                                   SWAPCHAIN_CREATE_SWAP_BAD_SHARING_VALUES, "%s() called with a supported "
1521                                                                             "pCreateInfo->sharingMode of (i.e. %s),"
1522                                                                             "but with a bad value(s) for "
1523                                                                             "pCreateInfo->queueFamilyIndexCount or "
1524                                                                             "pCreateInfo->pQueueFamilyIndices).",
1525                                   fn, sharingModeStr(pCreateInfo->imageSharingMode));
1526         }
1527     } else if (pCreateInfo->imageSharingMode != VK_SHARING_MODE_EXCLUSIVE) {
1528         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_BAD_SHARING_MODE,
1529                               "%s() called with a non-supported "
1530                               "pCreateInfo->imageSharingMode (i.e. %s).",
1531                               fn, sharingModeStr(pCreateInfo->imageSharingMode));
1532     }
1533 
1534     // Validate pCreateInfo->clipped:
1535     if (pCreateInfo && (pCreateInfo->clipped != VK_FALSE) && (pCreateInfo->clipped != VK_TRUE)) {
1536         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_BAD_BOOL,
1537                               "%s() called with a VkBool32 value that is "
1538                               "neither VK_TRUE nor VK_FALSE, but has the "
1539                               "numeric value of %d.",
1540                               fn, pCreateInfo->clipped);
1541     }
1542 
1543     // Validate pCreateInfo->oldSwapchain:
1544     if (pCreateInfo && pCreateInfo->oldSwapchain) {
1545         SwpSwapchain *pOldSwapchain = &my_data->swapchainMap[pCreateInfo->oldSwapchain];
1546         if (pOldSwapchain) {
1547             if (device != pOldSwapchain->pDevice->device) {
1548                 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1549                                       SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE, "%s() called with a different VkDevice "
1550                                                                           "than the VkSwapchainKHR was created with.",
1551                                       __FUNCTION__);
1552             }
1553             if (pCreateInfo->surface != pOldSwapchain->pSurface->surface) {
1554                 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1555                                       SWAPCHAIN_CREATE_SWAP_DIFF_SURFACE, "%s() called with pCreateInfo->oldSwapchain "
1556                                                                           "that has a different VkSurfaceKHR than "
1557                                                                           "pCreateInfo->surface.",
1558                                       fn);
1559             }
1560         } else {
1561             // TBD: Leave this in (not sure object_track will check this)?
1562             skipCall |=
1563                 LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pCreateInfo->oldSwapchain, "VkSwapchainKHR");
1564         }
1565     }
1566 
1567     return skipCall;
1568 }
1569 
vkCreateSwapchainKHR(VkDevice device,const VkSwapchainCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSwapchainKHR * pSwapchain)1570 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
1571                                                                     const VkAllocationCallbacks *pAllocator,
1572                                                                     VkSwapchainKHR *pSwapchain) {
1573     VkResult result = VK_SUCCESS;
1574     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1575     loader_platform_thread_lock_mutex(&globalLock);
1576     VkBool32 skipCall = validateCreateSwapchainKHR(device, pCreateInfo, pSwapchain);
1577 
1578     if (VK_FALSE == skipCall) {
1579         // Call down the call chain:
1580         loader_platform_thread_unlock_mutex(&globalLock);
1581         result = my_data->device_dispatch_table->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
1582         loader_platform_thread_lock_mutex(&globalLock);
1583 
1584         if (result == VK_SUCCESS) {
1585             // Remember the swapchain's handle, and link it to the device:
1586             SwpDevice *pDevice = &my_data->deviceMap[device];
1587 
1588             my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
1589             if (pDevice) {
1590                 pDevice->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
1591             }
1592             my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
1593             my_data->swapchainMap[*pSwapchain].imageCount = 0;
1594             my_data->swapchainMap[*pSwapchain].usedAllocatorToCreate = (pAllocator != NULL);
1595             // Store a pointer to the surface
1596             SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
1597             SwpInstance *pInstance = (pPhysicalDevice) ? pPhysicalDevice->pInstance : NULL;
1598             layer_data *my_instance_data =
1599                 ((pInstance) ? get_my_data_ptr(get_dispatch_key(pInstance->instance), layer_data_map) : NULL);
1600             SwpSurface *pSurface = ((my_data && pCreateInfo) ? &my_instance_data->surfaceMap[pCreateInfo->surface] : NULL);
1601             my_data->swapchainMap[*pSwapchain].pSurface = pSurface;
1602             if (pSurface) {
1603                 pSurface->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
1604             }
1605         }
1606         loader_platform_thread_unlock_mutex(&globalLock);
1607         return result;
1608     }
1609     loader_platform_thread_unlock_mutex(&globalLock);
1610     return VK_ERROR_VALIDATION_FAILED_EXT;
1611 }
1612 
1613 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
vkDestroySwapchainKHR(VkDevice device,VkSwapchainKHR swapchain,const VkAllocationCallbacks * pAllocator)1614 vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) {
1615     // TODOs:
1616     //
1617     // - Implement a check for validity language that reads: All uses of
1618     //   presentable images acquired from pname:swapchain and owned by the
1619     //   application must: have completed execution
1620     VkBool32 skipCall = VK_FALSE;
1621     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1622     loader_platform_thread_lock_mutex(&globalLock);
1623     SwpDevice *pDevice = &my_data->deviceMap[device];
1624 
1625     // Validate that the swapchain extension was enabled:
1626     if (pDevice && !pDevice->swapchainExtensionEnabled) {
1627         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1628                               "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
1629                               VK_KHR_SWAPCHAIN_EXTENSION_NAME);
1630     }
1631 
1632     // Regardless of skipCall value, do some internal cleanup:
1633     SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
1634     if (pSwapchain) {
1635         // Delete the SwpSwapchain associated with this swapchain:
1636         if (pSwapchain->pDevice) {
1637             pSwapchain->pDevice->swapchains.erase(swapchain);
1638             if (device != pSwapchain->pDevice->device) {
1639                 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
1640                           "%s() called with a different VkDevice than the "
1641                           "VkSwapchainKHR was created with.",
1642                           __FUNCTION__);
1643             }
1644         }
1645         if (pSwapchain->pSurface) {
1646             pSwapchain->pSurface->swapchains.erase(swapchain);
1647         }
1648         if (pSwapchain->imageCount) {
1649             pSwapchain->images.clear();
1650         }
1651         if ((pAllocator != NULL) != pSwapchain->usedAllocatorToCreate) {
1652             LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
1653                       "%s() called with incompatible pAllocator from when "
1654                       "the object was created.",
1655                       __FUNCTION__);
1656         }
1657         my_data->swapchainMap.erase(swapchain);
1658     }
1659     loader_platform_thread_unlock_mutex(&globalLock);
1660 
1661     if (VK_FALSE == skipCall) {
1662         // Call down the call chain:
1663         my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator);
1664     }
1665 }
1666 
1667 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkGetSwapchainImagesKHR(VkDevice device,VkSwapchainKHR swapchain,uint32_t * pSwapchainImageCount,VkImage * pSwapchainImages)1668 vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
1669     VkResult result = VK_SUCCESS;
1670     VkBool32 skipCall = VK_FALSE;
1671     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1672     loader_platform_thread_lock_mutex(&globalLock);
1673     SwpDevice *pDevice = &my_data->deviceMap[device];
1674 
1675     // Validate that the swapchain extension was enabled:
1676     if (pDevice && !pDevice->swapchainExtensionEnabled) {
1677         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1678                               "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
1679                               VK_KHR_SWAPCHAIN_EXTENSION_NAME);
1680     }
1681     SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
1682     if (!pSwapchainImageCount) {
1683         skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchainImageCount");
1684     }
1685 
1686     if (VK_FALSE == skipCall) {
1687         // Call down the call chain:
1688         loader_platform_thread_unlock_mutex(&globalLock);
1689         result = my_data->device_dispatch_table->GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
1690         loader_platform_thread_lock_mutex(&globalLock);
1691 
1692         // Obtain this pointer again after locking:
1693         pSwapchain = &my_data->swapchainMap[swapchain];
1694         if ((result == VK_SUCCESS) && pSwapchain && !pSwapchainImages && pSwapchainImageCount) {
1695             // Record the result of this preliminary query:
1696             pSwapchain->imageCount = *pSwapchainImageCount;
1697         } else if ((result == VK_SUCCESS) && pSwapchain && pSwapchainImages && pSwapchainImageCount) {
1698             // Compare the preliminary value of *pSwapchainImageCount with the
1699             // value this time:
1700             if (*pSwapchainImageCount > pSwapchain->imageCount) {
1701                 LOG_ERROR_INVALID_COUNT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchainImageCount", "pSwapchainImages",
1702                                         *pSwapchainImageCount, pSwapchain->imageCount);
1703             } else if (*pSwapchainImageCount > 0) {
1704                 // Record the images and their state:
1705                 pSwapchain->imageCount = *pSwapchainImageCount;
1706                 for (uint32_t i = 0; i < *pSwapchainImageCount; i++) {
1707                     pSwapchain->images[i].image = pSwapchainImages[i];
1708                     pSwapchain->images[i].pSwapchain = pSwapchain;
1709                     pSwapchain->images[i].ownedByApp = false;
1710                 }
1711             }
1712         }
1713         loader_platform_thread_unlock_mutex(&globalLock);
1714         return result;
1715     }
1716     loader_platform_thread_unlock_mutex(&globalLock);
1717     return VK_ERROR_VALIDATION_FAILED_EXT;
1718 }
1719 
vkAcquireNextImageKHR(VkDevice device,VkSwapchainKHR swapchain,uint64_t timeout,VkSemaphore semaphore,VkFence fence,uint32_t * pImageIndex)1720 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
1721                                                                      VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
1722     // TODOs:
1723     //
1724     // - Address the timeout.  Possibilities include looking at the state of the
1725     //   swapchain's images, depending on the timeout value.
1726     // - Implement a check for validity language that reads: If pname:semaphore is
1727     //   not sname:VK_NULL_HANDLE it must: be unsignalled
1728     // - Implement a check for validity language that reads: If pname:fence is not
1729     //   sname:VK_NULL_HANDLE it must: be unsignalled and mustnot: be associated
1730     //   with any other queue command that has not yet completed execution on that
1731     //   queue
1732     // - Record/update the state of the swapchain, in case an error occurs
1733     //   (e.g. VK_ERROR_OUT_OF_DATE_KHR).
1734     VkResult result = VK_SUCCESS;
1735     VkBool32 skipCall = VK_FALSE;
1736     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1737     loader_platform_thread_lock_mutex(&globalLock);
1738     SwpDevice *pDevice = &my_data->deviceMap[device];
1739 
1740     // Validate that the swapchain extension was enabled:
1741     if (pDevice && !pDevice->swapchainExtensionEnabled) {
1742         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1743                               "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
1744                               VK_KHR_SWAPCHAIN_EXTENSION_NAME);
1745     }
1746     if ((semaphore == VK_NULL_HANDLE) && (fence == VK_NULL_HANDLE)) {
1747         skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_NO_SYNC_FOR_ACQUIRE,
1748                               "%s() called with both the semaphore and fence parameters set to "
1749                               "VK_NULL_HANDLE (at least one should be used).", __FUNCTION__);
1750     }
1751     SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
1752     if (pSwapchain) {
1753         // Look to see if the application is trying to own too many images at
1754         // the same time (i.e. not leave any to display):
1755         uint32_t imagesOwnedByApp = 0;
1756         for (uint32_t i = 0; i < pSwapchain->imageCount; i++) {
1757             if (pSwapchain->images[i].ownedByApp) {
1758                 imagesOwnedByApp++;
1759             }
1760         }
1761         if (imagesOwnedByApp >= (pSwapchain->imageCount - 1)) {
1762             skipCall |= LOG_PERF_WARNING(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, swapchain, "VkSwapchainKHR",
1763                                          SWAPCHAIN_APP_OWNS_TOO_MANY_IMAGES, "%s() called when the application "
1764                                                                              "already owns all presentable images "
1765                                                                              "in this swapchain except for the "
1766                                                                              "image currently being displayed.  "
1767                                                                              "This call to %s() cannot succeed "
1768                                                                              "unless another thread calls the "
1769                                                                              "vkQueuePresentKHR() function in "
1770                                                                              "order to release ownership of one of "
1771                                                                              "the presentable images of this "
1772                                                                              "swapchain.",
1773                                          __FUNCTION__, __FUNCTION__);
1774         }
1775     }
1776     if (!pImageIndex) {
1777         skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pImageIndex");
1778     }
1779 
1780     if (VK_FALSE == skipCall) {
1781         // Call down the call chain:
1782         loader_platform_thread_unlock_mutex(&globalLock);
1783         result = my_data->device_dispatch_table->AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
1784         loader_platform_thread_lock_mutex(&globalLock);
1785 
1786         // Obtain this pointer again after locking:
1787         pSwapchain = &my_data->swapchainMap[swapchain];
1788         if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) && pSwapchain) {
1789             // Change the state of the image (now owned by the application):
1790             pSwapchain->images[*pImageIndex].ownedByApp = true;
1791         }
1792         loader_platform_thread_unlock_mutex(&globalLock);
1793         return result;
1794     }
1795     loader_platform_thread_unlock_mutex(&globalLock);
1796     return VK_ERROR_VALIDATION_FAILED_EXT;
1797 }
1798 
vkQueuePresentKHR(VkQueue queue,const VkPresentInfoKHR * pPresentInfo)1799 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
1800     // TODOs:
1801     //
1802     // - Implement a check for validity language that reads: Any given element of
1803     //   sname:VkSemaphore in pname:pWaitSemaphores must: refer to a prior signal
1804     //   of that sname:VkSemaphore that won't be consumed by any other wait on that
1805     //   semaphore
1806     // - Record/update the state of the swapchain, in case an error occurs
1807     //   (e.g. VK_ERROR_OUT_OF_DATE_KHR).
1808     VkResult result = VK_SUCCESS;
1809     VkBool32 skipCall = VK_FALSE;
1810     layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
1811 
1812     if (!pPresentInfo) {
1813         skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
1814     } else {
1815         if (pPresentInfo->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR) {
1816             skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo",
1817                                               "VK_STRUCTURE_TYPE_PRESENT_INFO_KHR");
1818         }
1819         if (pPresentInfo->pNext != NULL) {
1820             skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
1821         }
1822         if (!pPresentInfo->swapchainCount) {
1823             skipCall |= LOG_ERROR_ZERO_VALUE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->swapchainCount");
1824         }
1825         if (!pPresentInfo->pSwapchains) {
1826             skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pSwapchains");
1827         }
1828         if (!pPresentInfo->pImageIndices) {
1829             skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pImageIndices");
1830         }
1831         // Note: pPresentInfo->pResults is allowed to be NULL
1832     }
1833 
1834     loader_platform_thread_lock_mutex(&globalLock);
1835     for (uint32_t i = 0; pPresentInfo && (i < pPresentInfo->swapchainCount); i++) {
1836         uint32_t index = pPresentInfo->pImageIndices[i];
1837         SwpSwapchain *pSwapchain = &my_data->swapchainMap[pPresentInfo->pSwapchains[i]];
1838         if (pSwapchain) {
1839             if (!pSwapchain->pDevice->swapchainExtensionEnabled) {
1840                 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, pSwapchain->pDevice, "VkDevice",
1841                                       SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1842                                       "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
1843                                       VK_KHR_SWAPCHAIN_EXTENSION_NAME);
1844             }
1845             if (index >= pSwapchain->imageCount) {
1846                 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
1847                                       SWAPCHAIN_INDEX_TOO_LARGE, "%s() called for an index that is too "
1848                                                                  "large (i.e. %d).  There are only %d "
1849                                                                  "images in this VkSwapchainKHR.\n",
1850                                       __FUNCTION__, index, pSwapchain->imageCount);
1851             } else {
1852                 if (!pSwapchain->images[index].ownedByApp) {
1853                     skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i],
1854                                           "VkSwapchainKHR", SWAPCHAIN_INDEX_NOT_IN_USE, "%s() returned an index (i.e. %d) "
1855                                                                                         "for an image that is not owned by "
1856                                                                                         "the application.",
1857                                           __FUNCTION__, index);
1858                 }
1859             }
1860             SwpQueue *pQueue = &my_data->queueMap[queue];
1861             SwpSurface *pSurface = pSwapchain->pSurface;
1862             if (pQueue && pSurface && pSurface->numQueueFamilyIndexSupport) {
1863                 uint32_t queueFamilyIndex = pQueue->queueFamilyIndex;
1864                 // Note: the 1st test is to ensure queueFamilyIndex is in range,
1865                 // and the 2nd test is the validation check:
1866                 if ((pSurface->numQueueFamilyIndexSupport > queueFamilyIndex) &&
1867                     (!pSurface->pQueueFamilyIndexSupport[queueFamilyIndex])) {
1868                     skipCall |=
1869                         LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
1870                                   SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, "%s() called with a swapchain whose "
1871                                                                               "surface is not supported for "
1872                                                                               "presention on this device with the "
1873                                                                               "queueFamilyIndex (i.e. %d) of the "
1874                                                                               "given queue.",
1875                                   __FUNCTION__, queueFamilyIndex);
1876                 }
1877             }
1878         }
1879     }
1880 
1881     if (VK_FALSE == skipCall) {
1882         // Call down the call chain:
1883         loader_platform_thread_unlock_mutex(&globalLock);
1884         result = my_data->device_dispatch_table->QueuePresentKHR(queue, pPresentInfo);
1885         loader_platform_thread_lock_mutex(&globalLock);
1886 
1887         if (pPresentInfo && ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR))) {
1888             for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
1889                 int index = pPresentInfo->pImageIndices[i];
1890                 SwpSwapchain *pSwapchain = &my_data->swapchainMap[pPresentInfo->pSwapchains[i]];
1891                 if (pSwapchain) {
1892                     // Change the state of the image (no longer owned by the
1893                     // application):
1894                     pSwapchain->images[index].ownedByApp = false;
1895                 }
1896             }
1897         }
1898         loader_platform_thread_unlock_mutex(&globalLock);
1899         return result;
1900     }
1901     loader_platform_thread_unlock_mutex(&globalLock);
1902     return VK_ERROR_VALIDATION_FAILED_EXT;
1903 }
1904 
1905 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
vkGetDeviceQueue(VkDevice device,uint32_t queueFamilyIndex,uint32_t queueIndex,VkQueue * pQueue)1906 vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
1907     VkBool32 skipCall = VK_FALSE;
1908     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1909 
1910     if (VK_FALSE == skipCall) {
1911         // Call down the call chain:
1912         my_data->device_dispatch_table->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
1913 
1914         // Remember the queue's handle, and link it to the device:
1915         loader_platform_thread_lock_mutex(&globalLock);
1916         SwpDevice *pDevice = &my_data->deviceMap[device];
1917         my_data->queueMap[&pQueue].queue = *pQueue;
1918         if (pDevice) {
1919             pDevice->queues[*pQueue] = &my_data->queueMap[*pQueue];
1920         }
1921         my_data->queueMap[&pQueue].pDevice = pDevice;
1922         my_data->queueMap[&pQueue].queueFamilyIndex = queueFamilyIndex;
1923         loader_platform_thread_unlock_mutex(&globalLock);
1924     }
1925 }
1926 
1927 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkCreateDebugReportCallbackEXT(VkInstance instance,const VkDebugReportCallbackCreateInfoEXT * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDebugReportCallbackEXT * pMsgCallback)1928 vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
1929                                const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
1930     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1931     VkResult result =
1932         my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
1933     if (VK_SUCCESS == result) {
1934         loader_platform_thread_lock_mutex(&globalLock);
1935         result = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback);
1936         loader_platform_thread_unlock_mutex(&globalLock);
1937     }
1938     return result;
1939 }
1940 
vkDestroyDebugReportCallbackEXT(VkInstance instance,VkDebugReportCallbackEXT msgCallback,const VkAllocationCallbacks * pAllocator)1941 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance,
1942                                                                            VkDebugReportCallbackEXT msgCallback,
1943                                                                            const VkAllocationCallbacks *pAllocator) {
1944     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1945     my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
1946     loader_platform_thread_lock_mutex(&globalLock);
1947     layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
1948     loader_platform_thread_unlock_mutex(&globalLock);
1949 }
1950 
1951 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
vkDebugReportMessageEXT(VkInstance instance,VkDebugReportFlagsEXT flags,VkDebugReportObjectTypeEXT objType,uint64_t object,size_t location,int32_t msgCode,const char * pLayerPrefix,const char * pMsg)1952 vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
1953                         size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
1954     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1955     my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix,
1956                                                             pMsg);
1957 }
1958 
vkGetDeviceProcAddr(VkDevice device,const char * funcName)1959 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char *funcName) {
1960     if (!strcmp("vkGetDeviceProcAddr", funcName))
1961         return (PFN_vkVoidFunction)vkGetDeviceProcAddr;
1962     if (!strcmp(funcName, "vkDestroyDevice"))
1963         return (PFN_vkVoidFunction)vkDestroyDevice;
1964 
1965     if (device == VK_NULL_HANDLE) {
1966         return NULL;
1967     }
1968 
1969     layer_data *my_data;
1970 
1971     my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1972     VkLayerDispatchTable *pDisp =  my_data->device_dispatch_table;
1973     if (!strcmp("vkCreateSwapchainKHR", funcName))
1974         return reinterpret_cast<PFN_vkVoidFunction>(vkCreateSwapchainKHR);
1975     if (!strcmp("vkDestroySwapchainKHR", funcName))
1976         return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySwapchainKHR);
1977     if (!strcmp("vkGetSwapchainImagesKHR", funcName))
1978         return reinterpret_cast<PFN_vkVoidFunction>(vkGetSwapchainImagesKHR);
1979     if (!strcmp("vkAcquireNextImageKHR", funcName))
1980         return reinterpret_cast<PFN_vkVoidFunction>(vkAcquireNextImageKHR);
1981     if (!strcmp("vkQueuePresentKHR", funcName))
1982         return reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR);
1983     if (!strcmp("vkGetDeviceQueue", funcName))
1984         return reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceQueue);
1985 
1986     if (pDisp->GetDeviceProcAddr == NULL)
1987         return NULL;
1988     return pDisp->GetDeviceProcAddr(device, funcName);
1989 }
1990 
vkGetInstanceProcAddr(VkInstance instance,const char * funcName)1991 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
1992     if (!strcmp("vkGetInstanceProcAddr", funcName))
1993         return (PFN_vkVoidFunction)vkGetInstanceProcAddr;
1994     if (!strcmp(funcName, "vkCreateInstance"))
1995         return (PFN_vkVoidFunction)vkCreateInstance;
1996     if (!strcmp(funcName, "vkDestroyInstance"))
1997         return (PFN_vkVoidFunction)vkDestroyInstance;
1998     if (!strcmp(funcName, "vkCreateDevice"))
1999         return (PFN_vkVoidFunction)vkCreateDevice;
2000     if (!strcmp(funcName, "vkEnumeratePhysicalDevices"))
2001         return (PFN_vkVoidFunction)vkEnumeratePhysicalDevices;
2002     if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
2003         return (PFN_vkVoidFunction)vkEnumerateInstanceLayerProperties;
2004     if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties"))
2005         return (PFN_vkVoidFunction)vkEnumerateDeviceLayerProperties;
2006     if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
2007         return (PFN_vkVoidFunction)vkEnumerateInstanceExtensionProperties;
2008     if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties"))
2009         return (PFN_vkVoidFunction)vkEnumerateDeviceExtensionProperties;
2010     if (!strcmp(funcName, "vkGetPhysicalDeviceQueueFamilyProperties"))
2011         return (PFN_vkVoidFunction)vkGetPhysicalDeviceQueueFamilyProperties;
2012 
2013     if (instance == VK_NULL_HANDLE) {
2014         return NULL;
2015     }
2016 
2017     PFN_vkVoidFunction addr;
2018 
2019     layer_data *my_data;
2020     my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2021     VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
2022     addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
2023     if (addr) {
2024         return addr;
2025     }
2026 
2027 #ifdef VK_USE_PLATFORM_ANDROID_KHR
2028     if (!strcmp("vkCreateAndroidSurfaceKHR", funcName))
2029         return reinterpret_cast<PFN_vkVoidFunction>(vkCreateAndroidSurfaceKHR);
2030 #endif // VK_USE_PLATFORM_ANDROID_KHR
2031 #ifdef VK_USE_PLATFORM_MIR_KHR
2032     if (!strcmp("vkCreateMirSurfaceKHR", funcName))
2033         return reinterpret_cast<PFN_vkVoidFunction>(vkCreateMirSurfaceKHR);
2034     if (!strcmp("vkGetPhysicalDeviceMirPresentationSupportKHR", funcName))
2035         return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceMirPresentationSupportKHR);
2036 #endif // VK_USE_PLATFORM_MIR_KHR
2037 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
2038     if (!strcmp("vkCreateWaylandSurfaceKHR", funcName))
2039         return reinterpret_cast<PFN_vkVoidFunction>(vkCreateWaylandSurfaceKHR);
2040     if (!strcmp("vkGetPhysicalDeviceWaylandPresentationSupportKHR", funcName))
2041         return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceWaylandPresentationSupportKHR);
2042 #endif // VK_USE_PLATFORM_WAYLAND_KHR
2043 #ifdef VK_USE_PLATFORM_WIN32_KHR
2044     if (!strcmp("vkCreateWin32SurfaceKHR", funcName))
2045         return reinterpret_cast<PFN_vkVoidFunction>(vkCreateWin32SurfaceKHR);
2046     if (!strcmp("vkGetPhysicalDeviceWin32PresentationSupportKHR", funcName))
2047         return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceWin32PresentationSupportKHR);
2048 #endif // VK_USE_PLATFORM_WIN32_KHR
2049 #ifdef VK_USE_PLATFORM_XCB_KHR
2050     if (!strcmp("vkCreateXcbSurfaceKHR", funcName))
2051         return reinterpret_cast<PFN_vkVoidFunction>(vkCreateXcbSurfaceKHR);
2052     if (!strcmp("vkGetPhysicalDeviceXcbPresentationSupportKHR", funcName))
2053         return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceXcbPresentationSupportKHR);
2054 #endif // VK_USE_PLATFORM_XCB_KHR
2055 #ifdef VK_USE_PLATFORM_XLIB_KHR
2056     if (!strcmp("vkCreateXlibSurfaceKHR", funcName))
2057         return reinterpret_cast<PFN_vkVoidFunction>(vkCreateXlibSurfaceKHR);
2058     if (!strcmp("vkGetPhysicalDeviceXlibPresentationSupportKHR", funcName))
2059         return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceXlibPresentationSupportKHR);
2060 #endif // VK_USE_PLATFORM_XLIB_KHR
2061     if (!strcmp("vkDestroySurfaceKHR", funcName))
2062         return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySurfaceKHR);
2063     if (!strcmp("vkGetPhysicalDeviceSurfaceSupportKHR", funcName))
2064         return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceSupportKHR);
2065     if (!strcmp("vkGetPhysicalDeviceSurfaceCapabilitiesKHR", funcName))
2066         return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
2067     if (!strcmp("vkGetPhysicalDeviceSurfaceFormatsKHR", funcName))
2068         return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceFormatsKHR);
2069     if (!strcmp("vkGetPhysicalDeviceSurfacePresentModesKHR", funcName))
2070         return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfacePresentModesKHR);
2071 
2072     if (pTable->GetInstanceProcAddr == NULL)
2073         return NULL;
2074     return pTable->GetInstanceProcAddr(instance, funcName);
2075 }
2076