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