blob: 2fffbab1ad45dad5f445afe5bcb0dd6c80f506de [file] [log] [blame]
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -07001/* 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.
Ian Elliott0b4d6242015-09-22 10:51:24 -06005 *
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -07006 * 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:
Ian Elliott0b4d6242015-09-22 10:51:24 -060012 *
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -070013 * The above copyright notice(s) and this permission notice shall be included
14 * in all copies or substantial portions of the Materials.
Ian Elliott0b4d6242015-09-22 10:51:24 -060015 *
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -070016 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Ian Elliott0b4d6242015-09-22 10:51:24 -060017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -070018 * 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
Ian Elliott0b4d6242015-09-22 10:51:24 -060024 *
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060025 * Author: Ian Elliott <ian@lunarg.com>
Ian Elliott578e7e22016-01-05 14:03:16 -070026 * Author: Ian Elliott <ianelliott@google.com>
Ian Elliott0b4d6242015-09-22 10:51:24 -060027 */
28
Ian Elliottd8c5db12015-10-07 11:32:31 -060029#include <stdio.h>
30#include <string.h>
Mark Lobodzinskib49b6e52015-11-26 10:59:58 -070031#include <vk_loader_platform.h>
Cody Northropd08141b2016-02-01 09:52:07 -070032#include <vulkan/vk_icd.h>
Ian Elliott0b4d6242015-09-22 10:51:24 -060033#include "swapchain.h"
Tobin Ehlis711ff312015-10-29 12:58:13 -060034#include "vk_layer_extension_utils.h"
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070035#include "vk_enum_string_helper.h"
Ian Elliott68124ac2015-10-07 16:18:35 -060036
Ian Elliott32311832016-02-04 08:17:18 -070037static int globalLockInitialized = 0;
38static loader_platform_thread_mutex globalLock;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070039
Ian Elliott0b4d6242015-09-22 10:51:24 -060040// The following is for logging error messages:
Ian Elliott68124ac2015-10-07 16:18:35 -060041static std::unordered_map<void *, layer_data *> layer_data_map;
Ian Elliott0b4d6242015-09-22 10:51:24 -060042
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070043template layer_data *get_my_data_ptr<layer_data>(
44 void *data_key,
45 std::unordered_map<void *, layer_data *> &data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -060046
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -070047static const VkExtensionProperties instance_extensions[] = {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070048 {
49 VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
50 VK_EXT_DEBUG_REPORT_SPEC_VERSION
51 }
52};
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -070053
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070054VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
55 const char *pLayerName,
56 uint32_t *pCount,
57 VkExtensionProperties* pProperties)
58{
59 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -070060}
61
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070062static const VkLayerProperties swapchain_global_layers[] = {
63 {
Courtney Goeltzenleuchter0271ec22016-02-06 17:30:10 -070064 "VK_LAYER_LUNARG_swapchain",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070065 VK_API_VERSION,
Courtney Goeltzenleuchterf6ca21c2016-02-06 17:22:25 -070066 1,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070067 "Validation layer: swapchain",
68 }
69};
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -070070
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070071VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
72 uint32_t *pCount,
73 VkLayerProperties* pProperties)
74{
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -070075 return util_GetLayerProperties(ARRAY_SIZE(swapchain_global_layers),
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070076 swapchain_global_layers,
77 pCount, pProperties);
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -070078}
79
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070080static void createDeviceRegisterExtensions(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, VkDevice device)
81{
Ian Elliott0b4d6242015-09-22 10:51:24 -060082 uint32_t i;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070083 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
84 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -060085
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070086 VkLayerDispatchTable *pDisp = my_device_data->device_dispatch_table;
87 PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr;
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070088
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070089 pDisp->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR) gpa(device, "vkCreateSwapchainKHR");
90 pDisp->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR) gpa(device, "vkDestroySwapchainKHR");
91 pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR) gpa(device, "vkGetSwapchainImagesKHR");
92 pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR) gpa(device, "vkAcquireNextImageKHR");
93 pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR) gpa(device, "vkQueuePresentKHR");
94 pDisp->GetDeviceQueue = (PFN_vkGetDeviceQueue) gpa(device, "vkGetDeviceQueue");
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070095
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070096 SwpPhysicalDevice *pPhysicalDevice = &my_instance_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -060097 if (pPhysicalDevice) {
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070098 my_device_data->deviceMap[device].pPhysicalDevice = pPhysicalDevice;
99 pPhysicalDevice->pDevice = &my_device_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600100 } else {
Ian Elliott07adb112016-01-05 12:51:03 -0700101 // TBD: Should we leave error in (since Swapchain really needs this
102 // link)?
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700103 log_msg(my_instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
104 (uint64_t)physicalDevice , __LINE__, SWAPCHAIN_INVALID_HANDLE, "Swapchain",
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700105 "vkCreateDevice() called with a non-valid VkPhysicalDevice.");
Ian Elliott0b4d6242015-09-22 10:51:24 -0600106 }
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700107 my_device_data->deviceMap[device].device = device;
Ian Elliott427058f2015-12-29 16:45:49 -0700108 my_device_data->deviceMap[device].swapchainExtensionEnabled = false;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600109
110 // Record whether the WSI device extension was enabled for this VkDevice.
111 // No need to check if the extension was advertised by
112 // vkEnumerateDeviceExtensionProperties(), since the loader handles that.
Jon Ashburnf19916e2016-01-11 13:12:43 -0700113 for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700114 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600115
Ian Elliott427058f2015-12-29 16:45:49 -0700116 my_device_data->deviceMap[device].swapchainExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600117 }
118 }
119}
120
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700121static void createInstanceRegisterExtensions(const VkInstanceCreateInfo* pCreateInfo, VkInstance instance)
122{
Ian Elliott0b4d6242015-09-22 10:51:24 -0600123 uint32_t i;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700124 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
125 VkLayerInstanceDispatchTable *pDisp = my_data->instance_dispatch_table;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600126 PFN_vkGetInstanceProcAddr gpa = pDisp->GetInstanceProcAddr;
Ian Elliotta983e9a2015-12-22 12:18:12 -0700127#ifdef VK_USE_PLATFORM_ANDROID_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700128 pDisp->CreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR) gpa(instance, "vkCreateAndroidSurfaceKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -0700129#endif // VK_USE_PLATFORM_ANDROID_KHR
130#ifdef VK_USE_PLATFORM_MIR_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700131 pDisp->CreateMirSurfaceKHR = (PFN_vkCreateMirSurfaceKHR) gpa(instance, "vkCreateMirSurfaceKHR");
132 pDisp->GetPhysicalDeviceMirPresentationSupportKHR = (PFN_vkGetPhysicalDeviceMirPresentationSupportKHR) gpa(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -0700133#endif // VK_USE_PLATFORM_MIR_KHR
134#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700135 pDisp->CreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR) gpa(instance, "vkCreateWaylandSurfaceKHR");
136 pDisp->GetPhysicalDeviceWaylandPresentationSupportKHR = (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR) gpa(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -0700137#endif // VK_USE_PLATFORM_WAYLAND_KHR
138#ifdef VK_USE_PLATFORM_WIN32_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700139 pDisp->CreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR) gpa(instance, "vkCreateWin32SurfaceKHR");
140 pDisp->GetPhysicalDeviceWin32PresentationSupportKHR = (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR) gpa(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -0700141#endif // VK_USE_PLATFORM_WIN32_KHR
142#ifdef VK_USE_PLATFORM_XCB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700143 pDisp->CreateXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR) gpa(instance, "vkCreateXcbSurfaceKHR");
144 pDisp->GetPhysicalDeviceXcbPresentationSupportKHR = (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR) gpa(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -0700145#endif // VK_USE_PLATFORM_XCB_KHR
146#ifdef VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700147 pDisp->CreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR) gpa(instance, "vkCreateXlibSurfaceKHR");
148 pDisp->GetPhysicalDeviceXlibPresentationSupportKHR = (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR) gpa(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -0700149#endif // VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700150 pDisp->DestroySurfaceKHR = (PFN_vkDestroySurfaceKHR) gpa(instance, "vkDestroySurfaceKHR");
151 pDisp->GetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceSupportKHR");
152 pDisp->GetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
153 pDisp->GetPhysicalDeviceSurfaceFormatsKHR = (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR");
154 pDisp->GetPhysicalDeviceSurfacePresentModesKHR = (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR) gpa(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR");
Ian Elliott0b4d6242015-09-22 10:51:24 -0600155
Ian Elliott1dcd1092015-11-17 17:29:40 -0700156 // Remember this instance, and whether the VK_KHR_surface extension
Ian Elliott0b4d6242015-09-22 10:51:24 -0600157 // was enabled for it:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600158 my_data->instanceMap[instance].instance = instance;
Ian Elliott1cb77a62015-12-29 16:44:39 -0700159 my_data->instanceMap[instance].surfaceExtensionEnabled = false;
Ian Elliott8dffaf32016-01-04 14:10:30 -0700160#ifdef VK_USE_PLATFORM_ANDROID_KHR
161 my_data->instanceMap[instance].androidSurfaceExtensionEnabled = false;
162#endif // VK_USE_PLATFORM_ANDROID_KHR
163#ifdef VK_USE_PLATFORM_MIR_KHR
164 my_data->instanceMap[instance].mirSurfaceExtensionEnabled = false;
165#endif // VK_USE_PLATFORM_MIR_KHR
166#ifdef VK_USE_PLATFORM_WAYLAND_KHR
167 my_data->instanceMap[instance].waylandSurfaceExtensionEnabled = false;
168#endif // VK_USE_PLATFORM_WAYLAND_KHR
169#ifdef VK_USE_PLATFORM_WIN32_KHR
170 my_data->instanceMap[instance].win32SurfaceExtensionEnabled = false;
171#endif // VK_USE_PLATFORM_WIN32_KHR
172#ifdef VK_USE_PLATFORM_XCB_KHR
173 my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = false;
174#endif // VK_USE_PLATFORM_XCB_KHR
175#ifdef VK_USE_PLATFORM_XLIB_KHR
176 my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = false;
177#endif // VK_USE_PLATFORM_XLIB_KHR
178
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700179
Ian Elliott0b4d6242015-09-22 10:51:24 -0600180 // Record whether the WSI instance extension was enabled for this
181 // VkInstance. No need to check if the extension was advertised by
182 // vkEnumerateInstanceExtensionProperties(), since the loader handles that.
Jon Ashburnf19916e2016-01-11 13:12:43 -0700183 for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700184 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600185
Ian Elliott1cb77a62015-12-29 16:44:39 -0700186 my_data->instanceMap[instance].surfaceExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600187 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700188#ifdef VK_USE_PLATFORM_ANDROID_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700189 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700190
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700191 my_data->instanceMap[instance].androidSurfaceExtensionEnabled = true;
Ian Elliott8dffaf32016-01-04 14:10:30 -0700192#endif // VK_USE_PLATFORM_ANDROID_KHR
193#ifdef VK_USE_PLATFORM_MIR_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700194 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_MIR_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700195
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700196 my_data->instanceMap[instance].mirSurfaceExtensionEnabled = true;
Ian Elliott8dffaf32016-01-04 14:10:30 -0700197#endif // VK_USE_PLATFORM_MIR_KHR
198#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700199 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700200
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700201 my_data->instanceMap[instance].waylandSurfaceExtensionEnabled = true;
Ian Elliott8dffaf32016-01-04 14:10:30 -0700202#endif // VK_USE_PLATFORM_WAYLAND_KHR
203#ifdef VK_USE_PLATFORM_WIN32_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700204 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700205
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700206 my_data->instanceMap[instance].win32SurfaceExtensionEnabled = true;
Ian Elliott8dffaf32016-01-04 14:10:30 -0700207#endif // VK_USE_PLATFORM_WIN32_KHR
208#ifdef VK_USE_PLATFORM_XCB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700209 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700210
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700211 my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = true;
Ian Elliott8dffaf32016-01-04 14:10:30 -0700212#endif // VK_USE_PLATFORM_XCB_KHR
213#ifdef VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700214 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700215
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700216 my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = true;
Ian Elliott8dffaf32016-01-04 14:10:30 -0700217#endif // VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700218 }
219 }
220}
221
Ian Elliott0b4d6242015-09-22 10:51:24 -0600222
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700223#include "vk_dispatch_table_helper.h"
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700224static void initSwapchain(layer_data *my_data, const VkAllocationCallbacks *pAllocator)
225{
226 uint32_t report_flags = 0;
227 uint32_t debug_action = 0;
228 FILE *log_output = NULL;
229 const char *option_str;
230 VkDebugReportCallbackEXT callback;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600231
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700232 // Initialize Swapchain options:
233 report_flags = getLayerOptionFlags("SwapchainReportFlags", 0);
234 getLayerOptionEnum("SwapchainDebugAction", (uint32_t *) &debug_action);
Ian Elliott07adb112016-01-05 12:51:03 -0700235
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700236 if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)
237 {
238 // Turn on logging, since it was requested:
239 option_str = getLayerOption("SwapchainLogFilename");
240 log_output = getLayerLogOutput(option_str, "Swapchain");
241 VkDebugReportCallbackCreateInfoEXT dbgInfo;
242 memset(&dbgInfo, 0, sizeof(dbgInfo));
243 dbgInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
244 dbgInfo.pfnCallback = log_callback;
245 dbgInfo.pUserData = log_output;
246 dbgInfo.flags = report_flags;
247 layer_create_msg_callback(my_data->report_data,
248 &dbgInfo,
249 pAllocator,
250 &callback);
251 my_data->logging_callback.push_back(callback);
252 }
253 if (debug_action & VK_DBG_LAYER_ACTION_DEBUG_OUTPUT) {
254 VkDebugReportCallbackCreateInfoEXT dbgInfo;
255 memset(&dbgInfo, 0, sizeof(dbgInfo));
256 dbgInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
257 dbgInfo.pfnCallback = win32_debug_output_msg;
258 dbgInfo.pUserData = log_output;
259 dbgInfo.flags = report_flags;
260 layer_create_msg_callback(my_data->report_data, &dbgInfo, pAllocator, &callback);
261 my_data->logging_callback.push_back(callback);
262 }
Ian Elliott32311832016-02-04 08:17:18 -0700263 if (!globalLockInitialized)
264 {
265 loader_platform_thread_create_mutex(&globalLock);
266 globalLockInitialized = 1;
267 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700268}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600269
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700270static const char *surfaceTransformStr(VkSurfaceTransformFlagBitsKHR value)
271{
272 // Return a string corresponding to the value:
273 return string_VkSurfaceTransformFlagBitsKHR(value);
274}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600275
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700276static const char *surfaceCompositeAlphaStr(VkCompositeAlphaFlagBitsKHR value)
277{
278 // Return a string corresponding to the value:
279 return string_VkCompositeAlphaFlagBitsKHR(value);
280}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600281
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700282static const char *presentModeStr(VkPresentModeKHR value)
283{
284 // Return a string corresponding to the value:
285 return string_VkPresentModeKHR(value);
286}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600287
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700288static const char *sharingModeStr(VkSharingMode value)
289{
290 // Return a string corresponding to the value:
291 return string_VkSharingMode(value);
292}
Ian Elliott07adb112016-01-05 12:51:03 -0700293
Ian Elliott0b4d6242015-09-22 10:51:24 -0600294
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700295VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance)
296{
297 VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600298
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700299 assert(chain_info->u.pLayerInfo);
300 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
301 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");
302 if (fpCreateInstance == NULL) {
303 return VK_ERROR_INITIALIZATION_FAILED;
304 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700305
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700306 // Advance the link info for the next element on the chain
307 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700308
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700309 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
310 if (result != VK_SUCCESS) {
311 return result;
312 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700313
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700314 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
315 my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
316 layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700317
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700318 my_data->report_data = debug_report_create_instance(
319 my_data->instance_dispatch_table,
320 *pInstance,
321 pCreateInfo->enabledExtensionCount,
322 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700323
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700324 // Call the following function after my_data is initialized:
325 createInstanceRegisterExtensions(pCreateInfo, *pInstance);
326 initSwapchain(my_data, pAllocator);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700327
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700328 return result;
329}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700330
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700331VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator)
332{
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700333 dispatch_key key = get_dispatch_key(instance);
334 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
335 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700336
Ian Elliott32311832016-02-04 08:17:18 -0700337 // Call down the call chain:
338 my_data->instance_dispatch_table->DestroyInstance(instance, pAllocator);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700339
Ian Elliott32311832016-02-04 08:17:18 -0700340 loader_platform_thread_lock_mutex(&globalLock);
341
Ian Elliott32311832016-02-04 08:17:18 -0700342 // Do additional internal cleanup:
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700343 if (pInstance) {
344 // Delete all of the SwpPhysicalDevice's, SwpSurface's, and the
345 // SwpInstance associated with this instance:
346 for (auto it = pInstance->physicalDevices.begin() ;
347 it != pInstance->physicalDevices.end() ; it++) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700348
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700349 // Free memory that was allocated for/by this SwpPhysicalDevice:
350 SwpPhysicalDevice *pPhysicalDevice = it->second;
351 if (pPhysicalDevice) {
Ian Elliott458696a2016-02-04 06:11:17 -0700352 if (pPhysicalDevice->pDevice) {
353 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance",
354 SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
355 "%s() called before all of its associated "
356 "VkDevices were destroyed.",
357 __FUNCTION__);
358 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700359 free(pPhysicalDevice->pSurfaceFormats);
360 free(pPhysicalDevice->pPresentModes);
361 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700362
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700363 // Erase the SwpPhysicalDevice's from the my_data->physicalDeviceMap (which
364 // are simply pointed to by the SwpInstance):
365 my_data->physicalDeviceMap.erase(it->second->physicalDevice);
366 }
367 for (auto it = pInstance->surfaces.begin() ;
368 it != pInstance->surfaces.end() ; it++) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700369
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700370 // Free memory that was allocated for/by this SwpPhysicalDevice:
371 SwpSurface *pSurface = it->second;
372 if (pSurface) {
373 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance",
374 SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
375 "%s() called before all of its associated "
376 "VkSurfaceKHRs were destroyed.",
377 __FUNCTION__);
378 }
379 }
380 my_data->instanceMap.erase(instance);
381 }
Mark Lobodzinski3c99d552016-02-04 13:50:23 -0700382
383 // Clean up logging callback, if any
384 while (my_data->logging_callback.size() > 0) {
385 VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
386 layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
387 my_data->logging_callback.pop_back();
388 }
389 layer_debug_report_destroy_instance(my_data->report_data);
390
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700391 delete my_data->instance_dispatch_table;
392 layer_data_map.erase(key);
Ian Elliott32311832016-02-04 08:17:18 -0700393 if (layer_data_map.empty()) {
394 // Release mutex when destroying last instance
395 loader_platform_thread_unlock_mutex(&globalLock);
396 loader_platform_thread_delete_mutex(&globalLock);
397 globalLockInitialized = 0;
398 } else {
399 loader_platform_thread_unlock_mutex(&globalLock);
400 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700401}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700402
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700403VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties(
404 VkPhysicalDevice physicalDevice,
405 uint32_t* pQueueFamilyPropertyCount,
406 VkQueueFamilyProperties* pQueueFamilyProperties)
407{
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700408 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700409
410 // Call down the call chain:
411 my_data->instance_dispatch_table->GetPhysicalDeviceQueueFamilyProperties(
412 physicalDevice,
413 pQueueFamilyPropertyCount,
414 pQueueFamilyProperties);
415
416 // Record the result of this query:
417 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700418 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Ian Elliott32311832016-02-04 08:17:18 -0700419 if (pPhysicalDevice &&
420 pQueueFamilyPropertyCount && !pQueueFamilyProperties) {
421 pPhysicalDevice->gotQueueFamilyPropertyCount = true;
422 pPhysicalDevice->numOfQueueFamilies =
423 *pQueueFamilyPropertyCount;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700424 }
Ian Elliott32311832016-02-04 08:17:18 -0700425 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700426}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700427
428#ifdef VK_USE_PLATFORM_ANDROID_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700429VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR(
430 VkInstance instance,
431 const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
432 const VkAllocationCallbacks* pAllocator,
433 VkSurfaceKHR* pSurface)
434{
435 VkResult result = VK_SUCCESS;
436 VkBool32 skipCall = VK_FALSE;
437 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700438 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700439 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700440
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700441 // Validate that the platform extension was enabled:
Cody Northropd08141b2016-02-01 09:52:07 -0700442 if (pInstance && !pInstance->androidSurfaceExtensionEnabled) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700443 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
444 pInstance,
445 "VkInstance",
446 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
447 "%s() called even though the %s extension was not enabled for this VkInstance.",
Cody Northropd08141b2016-02-01 09:52:07 -0700448 __FUNCTION__, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700449 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700450
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700451 if (!pCreateInfo) {
452 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
453 device,
454 "pCreateInfo");
455 } else {
456 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR) {
457 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
458 device,
459 "pCreateInfo",
460 "VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR");
461 }
462 if (pCreateInfo->pNext != NULL) {
463 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
464 device,
465 "pCreateInfo");
466 }
467 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700468
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700469 if (VK_FALSE == skipCall) {
470 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -0700471 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700472 result = my_data->instance_dispatch_table->CreateAndroidSurfaceKHR(
473 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliott32311832016-02-04 08:17:18 -0700474 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700475
Ian Elliott32311832016-02-04 08:17:18 -0700476 // Obtain this pointer again after locking:
477 pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700478 if ((result == VK_SUCCESS) && pInstance && pSurface) {
479 // Record the VkSurfaceKHR returned by the ICD:
480 my_data->surfaceMap[*pSurface].surface = *pSurface;
481 my_data->surfaceMap[*pSurface].pInstance = pInstance;
482 my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
483 (pAllocator != NULL);
484 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
485 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
486 // Point to the associated SwpInstance:
487 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
488 }
Ian Elliott32311832016-02-04 08:17:18 -0700489 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700490 return result;
491 }
Ian Elliott32311832016-02-04 08:17:18 -0700492 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700493 return VK_ERROR_VALIDATION_FAILED_EXT;
494}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700495#endif // VK_USE_PLATFORM_ANDROID_KHR
496
497#ifdef VK_USE_PLATFORM_MIR_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700498VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMirSurfaceKHR(
499 VkInstance instance,
500 const VkMirSurfaceCreateInfoKHR* pCreateInfo,
501 const VkAllocationCallbacks* pAllocator,
502 VkSurfaceKHR* pSurface)
503{
504 VkResult result = VK_SUCCESS;
505 VkBool32 skipCall = VK_FALSE;
506 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700507 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700508 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700509
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700510 // Validate that the platform extension was enabled:
511 if (pInstance && !pInstance->mirSurfaceExtensionEnabled) {
512 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
513 pInstance,
514 "VkInstance",
515 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
516 "%s() called even though the %s extension was not enabled for this VkInstance.",
517 __FUNCTION__, VK_KHR_MIR_SURFACE_EXTENSION_NAME);
518 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700519
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700520 if (!pCreateInfo) {
521 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
522 device,
523 "pCreateInfo");
524 } else {
525 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR) {
526 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
527 device,
528 "pCreateInfo",
529 "VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR");
530 }
531 if (pCreateInfo->pNext != NULL) {
532 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
533 device,
534 "pCreateInfo");
535 }
536 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700537
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700538 if (VK_FALSE == skipCall) {
539 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -0700540 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700541 result = my_data->instance_dispatch_table->CreateMirSurfaceKHR(
542 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliott32311832016-02-04 08:17:18 -0700543 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700544
Ian Elliott32311832016-02-04 08:17:18 -0700545 // Obtain this pointer again after locking:
546 pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700547 if ((result == VK_SUCCESS) && pInstance && pSurface) {
548 // Record the VkSurfaceKHR returned by the ICD:
549 my_data->surfaceMap[*pSurface].surface = *pSurface;
550 my_data->surfaceMap[*pSurface].pInstance = pInstance;
551 my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
552 (pAllocator != NULL);
553 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
554 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
555 // Point to the associated SwpInstance:
556 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
557 }
Ian Elliott32311832016-02-04 08:17:18 -0700558 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700559 return result;
560 }
Ian Elliott32311832016-02-04 08:17:18 -0700561 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700562 return VK_ERROR_VALIDATION_FAILED_EXT;
563}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700564
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700565VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceMirPresentationSupportKHR(
566 VkPhysicalDevice physicalDevice,
567 uint32_t queueFamilyIndex,
568 MirConnection* connection)
569{
570 VkBool32 result = VK_FALSE;
571 VkBool32 skipCall = VK_FALSE;
572 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700573 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700574 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700575
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700576 // Validate that the platform extension was enabled:
577 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
578 !pPhysicalDevice->pInstance->mirSurfaceExtensionEnabled) {
579 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
580 pPhysicalDevice->pInstance,
581 "VkInstance",
582 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
583 "%s() called even though the %s extension was not enabled for this VkInstance.",
584 __FUNCTION__, VK_KHR_MIR_SURFACE_EXTENSION_NAME);
585 }
586 if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
587 (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
588 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
589 pPhysicalDevice,
590 "VkPhysicalDevice",
591 queueFamilyIndex,
592 pPhysicalDevice->numOfQueueFamilies);
593 }
Ian Elliott32311832016-02-04 08:17:18 -0700594 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700595
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700596 if (VK_FALSE == skipCall) {
597 // Call down the call chain:
598 result = my_data->instance_dispatch_table->GetPhysicalDeviceMirPresentationSupportKHR(
599 physicalDevice, queueFamilyIndex, connection);
600 }
601 return result;
602}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700603#endif // VK_USE_PLATFORM_MIR_KHR
604
605#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700606VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR(
607 VkInstance instance,
608 const VkWaylandSurfaceCreateInfoKHR* pCreateInfo,
609 const VkAllocationCallbacks* pAllocator,
610 VkSurfaceKHR* pSurface)
611{
612 VkResult result = VK_SUCCESS;
613 VkBool32 skipCall = VK_FALSE;
614 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700615 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700616 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700617
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700618 // Validate that the platform extension was enabled:
619 if (pInstance && !pInstance->waylandSurfaceExtensionEnabled) {
620 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
621 pInstance,
622 "VkInstance",
623 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
624 "%s() called even though the %s extension was not enabled for this VkInstance.",
625 __FUNCTION__, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
626 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700627
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700628 if (!pCreateInfo) {
629 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
630 device,
631 "pCreateInfo");
632 } else {
633 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR) {
634 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
635 device,
636 "pCreateInfo",
637 "VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR");
638 }
639 if (pCreateInfo->pNext != NULL) {
640 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
641 device,
642 "pCreateInfo");
643 }
644 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700645
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700646 if (VK_FALSE == skipCall) {
647 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -0700648 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700649 result = my_data->instance_dispatch_table->CreateWaylandSurfaceKHR(
650 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliott32311832016-02-04 08:17:18 -0700651 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700652
Ian Elliott32311832016-02-04 08:17:18 -0700653 // Obtain this pointer again after locking:
654 pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700655 if ((result == VK_SUCCESS) && pInstance && pSurface) {
656 // Record the VkSurfaceKHR returned by the ICD:
657 my_data->surfaceMap[*pSurface].surface = *pSurface;
658 my_data->surfaceMap[*pSurface].pInstance = pInstance;
659 my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
660 (pAllocator != NULL);
661 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
662 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
663 // Point to the associated SwpInstance:
664 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
665 }
Ian Elliott32311832016-02-04 08:17:18 -0700666 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700667 return result;
668 }
Ian Elliott32311832016-02-04 08:17:18 -0700669 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700670 return VK_ERROR_VALIDATION_FAILED_EXT;
671}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700672
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700673VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWaylandPresentationSupportKHR(
674 VkPhysicalDevice physicalDevice,
675 uint32_t queueFamilyIndex,
676 struct wl_display* display)
677{
678 VkBool32 result = VK_FALSE;
679 VkBool32 skipCall = VK_FALSE;
680 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700681 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700682 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700683
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700684 // Validate that the platform extension was enabled:
685 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
686 !pPhysicalDevice->pInstance->waylandSurfaceExtensionEnabled) {
687 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
688 pPhysicalDevice->pInstance,
689 "VkInstance",
690 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
691 "%s() called even though the %s extension was not enabled for this VkInstance.",
692 __FUNCTION__, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
693 }
694 if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
695 (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
696 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
697 pPhysicalDevice,
698 "VkPhysicalDevice",
699 queueFamilyIndex,
700 pPhysicalDevice->numOfQueueFamilies);
701 }
Ian Elliott32311832016-02-04 08:17:18 -0700702 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700703
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700704 if (VK_FALSE == skipCall) {
705 // Call down the call chain:
706 result = my_data->instance_dispatch_table->GetPhysicalDeviceWaylandPresentationSupportKHR(
707 physicalDevice, queueFamilyIndex, display);
708 }
709 return result;
710}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700711#endif // VK_USE_PLATFORM_WAYLAND_KHR
712
713#ifdef VK_USE_PLATFORM_WIN32_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700714VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR(
715 VkInstance instance,
716 const VkWin32SurfaceCreateInfoKHR* pCreateInfo,
717 const VkAllocationCallbacks* pAllocator,
718 VkSurfaceKHR* pSurface)
719{
720 VkResult result = VK_SUCCESS;
721 VkBool32 skipCall = VK_FALSE;
722 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700723 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700724 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700725
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700726 // Validate that the platform extension was enabled:
727 if (pInstance && !pInstance->win32SurfaceExtensionEnabled) {
728 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
729 pInstance,
730 "VkInstance",
731 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
732 "%s() called even though the %s extension was not enabled for this VkInstance.",
733 __FUNCTION__, VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
734 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700735
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700736 if (!pCreateInfo) {
737 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
738 device,
739 "pCreateInfo");
740 } else {
741 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR) {
742 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
743 device,
744 "pCreateInfo",
745 "VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR");
746 }
747 if (pCreateInfo->pNext != NULL) {
748 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
749 device,
750 "pCreateInfo");
751 }
752 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700753
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700754 if (VK_FALSE == skipCall) {
755 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -0700756 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700757 result = my_data->instance_dispatch_table->CreateWin32SurfaceKHR(
758 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliott32311832016-02-04 08:17:18 -0700759 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700760
Ian Elliott32311832016-02-04 08:17:18 -0700761 // Obtain this pointer again after locking:
762 pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700763 if ((result == VK_SUCCESS) && pInstance && pSurface) {
764 // Record the VkSurfaceKHR returned by the ICD:
765 my_data->surfaceMap[*pSurface].surface = *pSurface;
766 my_data->surfaceMap[*pSurface].pInstance = pInstance;
767 my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
768 (pAllocator != NULL);
769 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
770 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
771 // Point to the associated SwpInstance:
772 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
773 }
Ian Elliott32311832016-02-04 08:17:18 -0700774 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700775 return result;
776 }
Ian Elliott32311832016-02-04 08:17:18 -0700777 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700778 return VK_ERROR_VALIDATION_FAILED_EXT;
779}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700780
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700781VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR(
782 VkPhysicalDevice physicalDevice,
783 uint32_t queueFamilyIndex)
784{
785 VkBool32 result = VK_FALSE;
786 VkBool32 skipCall = VK_FALSE;
787 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700788 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700789 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700790
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700791 // Validate that the platform extension was enabled:
792 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
793 !pPhysicalDevice->pInstance->win32SurfaceExtensionEnabled) {
794 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
795 pPhysicalDevice->pInstance,
796 "VkInstance",
797 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
798 "%s() called even though the %s extension was not enabled for this VkInstance.",
799 __FUNCTION__, VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
800 }
801 if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
802 (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
803 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
804 pPhysicalDevice,
805 "VkPhysicalDevice",
806 queueFamilyIndex,
807 pPhysicalDevice->numOfQueueFamilies);
808 }
Ian Elliott32311832016-02-04 08:17:18 -0700809 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700810
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700811 if (VK_FALSE == skipCall) {
812 // Call down the call chain:
813 result = my_data->instance_dispatch_table->GetPhysicalDeviceWin32PresentationSupportKHR(
814 physicalDevice, queueFamilyIndex);
815 }
816 return result;
817}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700818#endif // VK_USE_PLATFORM_WIN32_KHR
819
820#ifdef VK_USE_PLATFORM_XCB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700821VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(
822 VkInstance instance,
823 const VkXcbSurfaceCreateInfoKHR* pCreateInfo,
824 const VkAllocationCallbacks* pAllocator,
825 VkSurfaceKHR* pSurface)
826{
827 VkResult result = VK_SUCCESS;
828 VkBool32 skipCall = VK_FALSE;
829 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700830 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700831 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700832
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700833 // Validate that the platform extension was enabled:
834 if (pInstance && !pInstance->xcbSurfaceExtensionEnabled) {
835 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
836 pInstance,
837 "VkInstance",
838 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
839 "%s() called even though the %s extension was not enabled for this VkInstance.",
840 __FUNCTION__, VK_KHR_XCB_SURFACE_EXTENSION_NAME);
841 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700842
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700843 if (!pCreateInfo) {
844 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
845 device,
846 "pCreateInfo");
847 } else {
848 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR) {
849 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
850 device,
851 "pCreateInfo",
852 "VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR");
853 }
854 if (pCreateInfo->pNext != NULL) {
855 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
856 device,
857 "pCreateInfo");
858 }
859 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700860
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700861 if (VK_FALSE == skipCall) {
862 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -0700863 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700864 result = my_data->instance_dispatch_table->CreateXcbSurfaceKHR(
865 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliott32311832016-02-04 08:17:18 -0700866 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700867
Ian Elliott32311832016-02-04 08:17:18 -0700868 // Obtain this pointer again after locking:
869 pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700870 if ((result == VK_SUCCESS) && pInstance && pSurface) {
871 // Record the VkSurfaceKHR returned by the ICD:
872 my_data->surfaceMap[*pSurface].surface = *pSurface;
873 my_data->surfaceMap[*pSurface].pInstance = pInstance;
874 my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
875 (pAllocator != NULL);
876 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
877 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
878 // Point to the associated SwpInstance:
879 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
880 }
Ian Elliott32311832016-02-04 08:17:18 -0700881 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700882 return result;
883 }
Ian Elliott32311832016-02-04 08:17:18 -0700884 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700885 return VK_ERROR_VALIDATION_FAILED_EXT;
886}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700887
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700888VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXcbPresentationSupportKHR(
889 VkPhysicalDevice physicalDevice,
890 uint32_t queueFamilyIndex,
891 xcb_connection_t* connection,
892 xcb_visualid_t visual_id)
893{
894 VkBool32 result = VK_FALSE;
895 VkBool32 skipCall = VK_FALSE;
896 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700897 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700898 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700899
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700900 // Validate that the platform extension was enabled:
901 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
902 !pPhysicalDevice->pInstance->xcbSurfaceExtensionEnabled) {
903 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
904 pPhysicalDevice->pInstance,
905 "VkInstance",
906 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
907 "%s() called even though the %s extension was not enabled for this VkInstance.",
908 __FUNCTION__, VK_KHR_XCB_SURFACE_EXTENSION_NAME);
909 }
910 if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
911 (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
912 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
913 pPhysicalDevice,
914 "VkPhysicalDevice",
915 queueFamilyIndex,
916 pPhysicalDevice->numOfQueueFamilies);
917 }
Ian Elliott32311832016-02-04 08:17:18 -0700918 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700919
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700920 if (VK_FALSE == skipCall) {
921 // Call down the call chain:
922 result = my_data->instance_dispatch_table->GetPhysicalDeviceXcbPresentationSupportKHR(
923 physicalDevice, queueFamilyIndex, connection, visual_id);
924 }
925 return result;
926}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700927#endif // VK_USE_PLATFORM_XCB_KHR
928
929#ifdef VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700930VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(
931 VkInstance instance,
932 const VkXlibSurfaceCreateInfoKHR* pCreateInfo,
933 const VkAllocationCallbacks* pAllocator,
934 VkSurfaceKHR* pSurface)
935{
936 VkResult result = VK_SUCCESS;
937 VkBool32 skipCall = VK_FALSE;
938 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700939 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700940 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700941
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700942 // Validate that the platform extension was enabled:
943 if (pInstance && !pInstance->xlibSurfaceExtensionEnabled) {
944 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
945 pInstance,
946 "VkInstance",
947 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
948 "%s() called even though the %s extension was not enabled for this VkInstance.",
949 __FUNCTION__, VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
950 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700951
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700952 if (!pCreateInfo) {
953 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
954 device,
955 "pCreateInfo");
956 } else {
957 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR) {
958 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
959 device,
960 "pCreateInfo",
961 "VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR");
962 }
963 if (pCreateInfo->pNext != NULL) {
964 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
965 device,
966 "pCreateInfo");
967 }
968 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700969
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700970 if (VK_FALSE == skipCall) {
971 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -0700972 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700973 result = my_data->instance_dispatch_table->CreateXlibSurfaceKHR(
974 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliott32311832016-02-04 08:17:18 -0700975 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700976
Ian Elliott32311832016-02-04 08:17:18 -0700977 // Obtain this pointer again after locking:
978 pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700979 if ((result == VK_SUCCESS) && pInstance && pSurface) {
980 // Record the VkSurfaceKHR returned by the ICD:
981 my_data->surfaceMap[*pSurface].surface = *pSurface;
982 my_data->surfaceMap[*pSurface].pInstance = pInstance;
983 my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
984 (pAllocator != NULL);
985 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
986 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
987 // Point to the associated SwpInstance:
988 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
989 }
Ian Elliott32311832016-02-04 08:17:18 -0700990 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700991 return result;
992 }
Ian Elliott32311832016-02-04 08:17:18 -0700993 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700994 return VK_ERROR_VALIDATION_FAILED_EXT;
995}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700996
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700997VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR(
998 VkPhysicalDevice physicalDevice,
999 uint32_t queueFamilyIndex,
1000 Display* dpy,
1001 VisualID visualID)
1002{
1003 VkBool32 result = VK_FALSE;
1004 VkBool32 skipCall = VK_FALSE;
1005 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001006 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001007 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001008
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001009 // Validate that the platform extension was enabled:
1010 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
1011 !pPhysicalDevice->pInstance->xlibSurfaceExtensionEnabled) {
1012 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1013 pPhysicalDevice->pInstance,
1014 "VkInstance",
1015 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1016 "%s() called even though the %s extension was not enabled for this VkInstance.",
1017 __FUNCTION__, VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
1018 }
1019 if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
1020 (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
1021 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1022 pPhysicalDevice,
1023 "VkPhysicalDevice",
1024 queueFamilyIndex,
1025 pPhysicalDevice->numOfQueueFamilies);
1026 }
Ian Elliott32311832016-02-04 08:17:18 -07001027 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001028
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001029 if (VK_FALSE == skipCall) {
1030 // Call down the call chain:
1031 result = my_data->instance_dispatch_table->GetPhysicalDeviceXlibPresentationSupportKHR(
1032 physicalDevice, queueFamilyIndex, dpy, visualID);
1033 }
1034 return result;
1035}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001036#endif // VK_USE_PLATFORM_XLIB_KHR
1037
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001038VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator)
1039{
1040 VkBool32 skipCall = VK_FALSE;
1041 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001042 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001043 SwpSurface *pSurface = &my_data->surfaceMap[surface];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001044
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001045 // Regardless of skipCall value, do some internal cleanup:
1046 if (pSurface) {
1047 // Delete the SwpSurface associated with this surface:
1048 if (pSurface->pInstance) {
1049 pSurface->pInstance->surfaces.erase(surface);
1050 }
1051 if (!pSurface->swapchains.empty()) {
1052 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance",
1053 SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
1054 "%s() called before all of its associated "
1055 "VkSwapchainKHRs were destroyed.",
1056 __FUNCTION__);
1057 // Empty and then delete all SwpSwapchain's
1058 for (auto it = pSurface->swapchains.begin() ;
1059 it != pSurface->swapchains.end() ; it++) {
1060 // Delete all SwpImage's
1061 it->second->images.clear();
1062 // In case the swapchain's device hasn't been destroyed yet
1063 // (which isn't likely, but is possible), delete its
1064 // association with this swapchain (i.e. so we can't point to
1065 // this swpchain from that device, later on):
1066 if (it->second->pDevice) {
1067 it->second->pDevice->swapchains.clear();
1068 }
1069 }
1070 pSurface->swapchains.clear();
1071 }
1072 if ((pAllocator != NULL) != pSurface->usedAllocatorToCreate) {
1073 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance",
1074 SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
1075 "%s() called with incompatible pAllocator from when "
1076 "the object was created.",
1077 __FUNCTION__);
1078 }
1079 my_data->surfaceMap.erase(surface);
1080 }
Ian Elliott32311832016-02-04 08:17:18 -07001081 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001082
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001083 if (VK_FALSE == skipCall) {
1084 // Call down the call chain:
1085 my_data->instance_dispatch_table->DestroySurfaceKHR(
1086 instance, surface, pAllocator);
1087 }
1088}
1089
1090VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices)
1091{
1092 VkResult result = VK_SUCCESS;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001093 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001094
1095 // Call down the call chain:
1096 result = my_data->instance_dispatch_table->EnumeratePhysicalDevices(
1097 instance, pPhysicalDeviceCount, pPhysicalDevices);
1098
1099 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001100 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Ian Elliott32311832016-02-04 08:17:18 -07001101 if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices &&
1102 (*pPhysicalDeviceCount > 0)) {
1103 // Record the VkPhysicalDevices returned by the ICD:
1104 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
1105 my_data->physicalDeviceMap[pPhysicalDevices[i]].physicalDevice =
1106 pPhysicalDevices[i];
1107 my_data->physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance;
1108 my_data->physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL;
1109 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotQueueFamilyPropertyCount = false;
1110 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotSurfaceCapabilities = false;
1111 my_data->physicalDeviceMap[pPhysicalDevices[i]].surfaceFormatCount = 0;
1112 my_data->physicalDeviceMap[pPhysicalDevices[i]].pSurfaceFormats = NULL;
1113 my_data->physicalDeviceMap[pPhysicalDevices[i]].presentModeCount = 0;
1114 my_data->physicalDeviceMap[pPhysicalDevices[i]].pPresentModes = NULL;
1115 // Point to the associated SwpInstance:
1116 if (pInstance) {
1117 pInstance->physicalDevices[pPhysicalDevices[i]] =
1118 &my_data->physicalDeviceMap[pPhysicalDevices[i]];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001119 }
1120 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001121 }
Ian Elliott32311832016-02-04 08:17:18 -07001122 loader_platform_thread_unlock_mutex(&globalLock);
Ian Elliotta3c69bc2016-02-04 15:34:59 -07001123 return result;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001124}
1125
1126VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice)
1127{
1128 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
1129
1130 assert(chain_info->u.pLayerInfo);
1131 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
1132 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
1133 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
1134 if (fpCreateDevice == NULL) {
1135 return VK_ERROR_INITIALIZATION_FAILED;
1136 }
1137
1138 // Advance the link info for the next element on the chain
1139 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
1140
1141 VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1142 if (result != VK_SUCCESS) {
1143 return result;
1144 }
1145
Ian Elliott32311832016-02-04 08:17:18 -07001146 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001147 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1148 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
1149
1150 // Setup device dispatch table
1151 my_device_data->device_dispatch_table = new VkLayerDispatchTable;
1152 layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
1153
1154 my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
1155 createDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice);
Ian Elliott32311832016-02-04 08:17:18 -07001156 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001157
1158 return result;
1159}
1160
1161VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator)
1162{
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001163 dispatch_key key = get_dispatch_key(device);
1164 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001165
1166 // Call down the call chain:
1167 my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
1168
1169 // Do some internal cleanup:
1170 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001171 SwpDevice *pDevice = &my_data->deviceMap[device];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001172 if (pDevice) {
1173 // Delete the SwpDevice associated with this device:
1174 if (pDevice->pPhysicalDevice) {
1175 pDevice->pPhysicalDevice->pDevice = NULL;
1176 }
1177 if (!pDevice->swapchains.empty()) {
1178 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1179 SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
1180 "%s() called before all of its associated "
1181 "VkSwapchainKHRs were destroyed.",
1182 __FUNCTION__);
1183 // Empty and then delete all SwpSwapchain's
1184 for (auto it = pDevice->swapchains.begin() ;
1185 it != pDevice->swapchains.end() ; it++) {
1186 // Delete all SwpImage's
1187 it->second->images.clear();
1188 // In case the swapchain's surface hasn't been destroyed yet
1189 // (which is likely) delete its association with this swapchain
1190 // (i.e. so we can't point to this swpchain from that surface,
1191 // later on):
1192 if (it->second->pSurface) {
1193 it->second->pSurface->swapchains.clear();
1194 }
1195 }
1196 pDevice->swapchains.clear();
1197 }
1198 my_data->deviceMap.erase(device);
1199 }
1200 delete my_data->device_dispatch_table;
1201 layer_data_map.erase(key);
Ian Elliott32311832016-02-04 08:17:18 -07001202 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001203}
1204
1205VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(
1206 VkPhysicalDevice physicalDevice,
1207 uint32_t queueFamilyIndex,
1208 VkSurfaceKHR surface,
1209 VkBool32* pSupported)
1210{
1211 VkResult result = VK_SUCCESS;
1212 VkBool32 skipCall = VK_FALSE;
1213 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001214 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001215 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
1216
1217 // Validate that the surface extension was enabled:
1218 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
1219 !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1220 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1221 pPhysicalDevice->pInstance,
1222 "VkInstance",
1223 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1224 "%s() called even though the %s extension was not enabled for this VkInstance.",
1225 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
1226 }
1227 if (!pPhysicalDevice->gotQueueFamilyPropertyCount) {
1228 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1229 pPhysicalDevice,
1230 "VkPhysicalDevice",
1231 SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES,
1232 "%s() called before calling the "
1233 "vkGetPhysicalDeviceQueueFamilyProperties "
1234 "function.",
1235 __FUNCTION__);
1236 } else if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
1237 (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
1238 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1239 pPhysicalDevice,
1240 "VkPhysicalDevice",
1241 queueFamilyIndex,
1242 pPhysicalDevice->numOfQueueFamilies);
1243 }
1244 if (!pSupported) {
1245 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1246 physicalDevice,
1247 "pSupported");
1248 }
1249
1250 if (VK_FALSE == skipCall) {
1251 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -07001252 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001253 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(
1254 physicalDevice, queueFamilyIndex, surface,
1255 pSupported);
Ian Elliott32311832016-02-04 08:17:18 -07001256 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001257
Ian Elliott32311832016-02-04 08:17:18 -07001258 // Obtain this pointer again after locking:
1259 pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001260 if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
1261 // Record the result of this query:
1262 SwpInstance *pInstance = pPhysicalDevice->pInstance;
1263 SwpSurface *pSurface =
1264 (pInstance) ? pInstance->surfaces[surface] : NULL;
1265 if (pSurface) {
1266 pPhysicalDevice->supportedSurfaces[surface] = pSurface;
1267 if (!pSurface->numQueueFamilyIndexSupport) {
1268 if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
1269 pSurface->pQueueFamilyIndexSupport = (VkBool32 *)
1270 malloc(pPhysicalDevice->numOfQueueFamilies *
1271 sizeof(VkBool32));
1272 if (pSurface->pQueueFamilyIndexSupport != NULL) {
1273 pSurface->numQueueFamilyIndexSupport =
1274 pPhysicalDevice->numOfQueueFamilies;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001275 }
1276 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001277 }
1278 if (pSurface->numQueueFamilyIndexSupport) {
1279 pSurface->pQueueFamilyIndexSupport[queueFamilyIndex] =
1280 *pSupported;
1281 }
1282 }
1283 }
Ian Elliott32311832016-02-04 08:17:18 -07001284 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001285 return result;
1286 }
Ian Elliott32311832016-02-04 08:17:18 -07001287 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001288 return VK_ERROR_VALIDATION_FAILED_EXT;
1289}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001290
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001291VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
1292 VkPhysicalDevice physicalDevice,
1293 VkSurfaceKHR surface,
1294 VkSurfaceCapabilitiesKHR* pSurfaceCapabilities)
1295{
1296 VkResult result = VK_SUCCESS;
1297 VkBool32 skipCall = VK_FALSE;
1298 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001299 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001300 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001301
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001302 // Validate that the surface extension was enabled:
1303 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
1304 !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1305 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1306 pPhysicalDevice->pInstance,
1307 "VkInstance",
1308 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1309 "%s() called even though the %s extension was not enabled for this VkInstance.",
1310 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
1311 }
1312 if (!pSurfaceCapabilities) {
1313 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1314 physicalDevice,
1315 "pSurfaceCapabilities");
1316 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001317
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001318 if (VK_FALSE == skipCall) {
1319 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -07001320 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001321 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceCapabilitiesKHR(
1322 physicalDevice, surface, pSurfaceCapabilities);
Ian Elliott32311832016-02-04 08:17:18 -07001323 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001324
Ian Elliott32311832016-02-04 08:17:18 -07001325 // Obtain this pointer again after locking:
1326 pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001327 if ((result == VK_SUCCESS) && pPhysicalDevice) {
1328 // Record the result of this query:
1329 pPhysicalDevice->gotSurfaceCapabilities = true;
1330// FIXME: NEED TO COPY THIS DATA, BECAUSE pSurfaceCapabilities POINTS TO APP-ALLOCATED DATA
1331 pPhysicalDevice->surfaceCapabilities = *pSurfaceCapabilities;
1332 }
Ian Elliott32311832016-02-04 08:17:18 -07001333 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001334 return result;
1335 }
Ian Elliott32311832016-02-04 08:17:18 -07001336 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001337 return VK_ERROR_VALIDATION_FAILED_EXT;
1338}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001339
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001340VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR(
1341 VkPhysicalDevice physicalDevice,
1342 VkSurfaceKHR surface,
1343 uint32_t* pSurfaceFormatCount,
1344 VkSurfaceFormatKHR* pSurfaceFormats)
1345{
1346 VkResult result = VK_SUCCESS;
1347 VkBool32 skipCall = VK_FALSE;
1348 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001349 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001350 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001351
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001352 // Validate that the surface extension was enabled:
1353 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
1354 !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1355 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1356 pPhysicalDevice->pInstance,
1357 "VkInstance",
1358 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1359 "%s() called even though the %s extension was not enabled for this VkInstance.",
1360 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
1361 }
1362 if (!pSurfaceFormatCount) {
1363 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1364 physicalDevice,
1365 "pSurfaceFormatCount");
1366 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001367
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001368 if (VK_FALSE == skipCall) {
1369 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -07001370 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001371 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceFormatsKHR(
1372 physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats);
Ian Elliott32311832016-02-04 08:17:18 -07001373 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001374
Ian Elliott32311832016-02-04 08:17:18 -07001375 // Obtain this pointer again after locking:
1376 pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001377 if ((result == VK_SUCCESS) && pPhysicalDevice && !pSurfaceFormats &&
1378 pSurfaceFormatCount) {
1379 // Record the result of this preliminary query:
1380 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
1381 }
1382 else if ((result == VK_SUCCESS) && pPhysicalDevice && pSurfaceFormats &&
1383 pSurfaceFormatCount) {
1384 // Compare the preliminary value of *pSurfaceFormatCount with the
1385 // value this time:
1386 if (*pSurfaceFormatCount > pPhysicalDevice->surfaceFormatCount) {
1387 LOG_ERROR_INVALID_COUNT(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1388 physicalDevice,
1389 "pSurfaceFormatCount",
1390 "pSurfaceFormats",
1391 *pSurfaceFormatCount,
Ian Elliottf955d682015-12-30 12:00:54 -07001392 pPhysicalDevice->surfaceFormatCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001393 }
1394 else if (*pSurfaceFormatCount > 0) {
1395 // Record the result of this query:
1396 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
1397 pPhysicalDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)
1398 malloc(*pSurfaceFormatCount * sizeof(VkSurfaceFormatKHR));
1399 if (pPhysicalDevice->pSurfaceFormats) {
1400 for (uint32_t i = 0 ; i < *pSurfaceFormatCount ; i++) {
1401 pPhysicalDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
Ian Elliott9059b302015-12-30 13:14:36 -07001402 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001403 } else {
1404 pPhysicalDevice->surfaceFormatCount = 0;
1405 }
1406 }
1407 }
Ian Elliott32311832016-02-04 08:17:18 -07001408 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001409 return result;
1410 }
Ian Elliott32311832016-02-04 08:17:18 -07001411 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001412 return VK_ERROR_VALIDATION_FAILED_EXT;
1413}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001414
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001415VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR(
1416 VkPhysicalDevice physicalDevice,
1417 VkSurfaceKHR surface,
1418 uint32_t* pPresentModeCount,
1419 VkPresentModeKHR* pPresentModes)
1420{
1421 VkResult result = VK_SUCCESS;
1422 VkBool32 skipCall = VK_FALSE;
1423 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001424 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001425 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Ian Elliott07adb112016-01-05 12:51:03 -07001426
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001427 // Validate that the surface extension was enabled:
1428 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
1429 !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1430 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1431 pPhysicalDevice->pInstance,
1432 "VkInstance",
1433 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1434 "%s() called even though the %s extension was not enabled for this VkInstance.",
1435 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
1436 }
1437 if (!pPresentModeCount) {
1438 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1439 physicalDevice,
1440 "pPresentModeCount");
1441 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001442
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001443 if (VK_FALSE == skipCall) {
1444 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -07001445 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001446 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfacePresentModesKHR(
1447 physicalDevice, surface, pPresentModeCount, pPresentModes);
Ian Elliott32311832016-02-04 08:17:18 -07001448 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001449
Ian Elliott32311832016-02-04 08:17:18 -07001450 // Obtain this pointer again after locking:
1451 pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001452 if ((result == VK_SUCCESS) && pPhysicalDevice && !pPresentModes &&
1453 pPresentModeCount) {
1454 // Record the result of this preliminary query:
1455 pPhysicalDevice->presentModeCount = *pPresentModeCount;
1456 }
1457 else if ((result == VK_SUCCESS) && pPhysicalDevice && pPresentModes &&
1458 pPresentModeCount) {
1459 // Compare the preliminary value of *pPresentModeCount with the
1460 // value this time:
1461 if (*pPresentModeCount > pPhysicalDevice->presentModeCount) {
1462 LOG_ERROR_INVALID_COUNT(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1463 physicalDevice,
1464 "pPresentModeCount",
1465 "pPresentModes",
1466 *pPresentModeCount,
Ian Elliottf955d682015-12-30 12:00:54 -07001467 pPhysicalDevice->presentModeCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001468 }
1469 else if (*pPresentModeCount > 0) {
1470 // Record the result of this query:
1471 pPhysicalDevice->presentModeCount = *pPresentModeCount;
1472 pPhysicalDevice->pPresentModes = (VkPresentModeKHR *)
1473 malloc(*pPresentModeCount * sizeof(VkPresentModeKHR));
1474 if (pPhysicalDevice->pPresentModes) {
1475 for (uint32_t i = 0 ; i < *pPresentModeCount ; i++) {
1476 pPhysicalDevice->pPresentModes[i] = pPresentModes[i];
Ian Elliott9059b302015-12-30 13:14:36 -07001477 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001478 } else {
1479 pPhysicalDevice->presentModeCount = 0;
1480 }
1481 }
1482 }
Ian Elliott32311832016-02-04 08:17:18 -07001483 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001484 return result;
1485 }
Ian Elliott32311832016-02-04 08:17:18 -07001486 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001487 return VK_ERROR_VALIDATION_FAILED_EXT;
1488}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001489
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001490// This function does the up-front validation work for vkCreateSwapchainKHR(),
1491// and returns VK_TRUE if a logging callback indicates that the call down the
1492// chain should be skipped:
1493static VkBool32 validateCreateSwapchainKHR(
1494 VkDevice device,
1495 const VkSwapchainCreateInfoKHR* pCreateInfo,
1496 VkSwapchainKHR* pSwapchain)
1497{
1498// TODO: Validate cases of re-creating a swapchain (the current code
1499// assumes a new swapchain is being created).
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001500 VkBool32 skipCall = VK_FALSE;
1501 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1502 char fn[] = "vkCreateSwapchainKHR";
1503 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001504
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001505 // Validate that the swapchain extension was enabled:
1506 if (pDevice && !pDevice->swapchainExtensionEnabled) {
1507 return LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1508 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1509 "%s() called even though the %s extension was not enabled for this VkDevice.",
1510 fn, VK_KHR_SWAPCHAIN_EXTENSION_NAME );
1511 }
1512 if (!pCreateInfo) {
1513 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1514 device,
1515 "pCreateInfo");
1516 } else {
1517 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR) {
1518 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1519 device,
1520 "pCreateInfo",
1521 "VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR");
1522 }
1523 if (pCreateInfo->pNext != NULL) {
1524 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1525 device,
1526 "pCreateInfo");
1527 }
1528 }
1529 if (!pSwapchain) {
1530 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1531 device,
1532 "pSwapchain");
1533 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001534
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001535 // Keep around a useful pointer to pPhysicalDevice:
1536 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001537
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001538 // Validate pCreateInfo values with the results of
1539 // vkGetPhysicalDeviceSurfaceCapabilitiesKHR():
1540 if (!pPhysicalDevice || !pPhysicalDevice->gotSurfaceCapabilities) {
1541 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1542 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
1543 "%s() called before calling "
1544 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1545 fn);
1546 } else if (pCreateInfo) {
1547 // Validate pCreateInfo->surface to make sure that
1548 // vkGetPhysicalDeviceSurfaceSupportKHR() reported this as a supported
1549 // surface:
1550 SwpSurface *pSurface =
1551 ((pPhysicalDevice) ?
1552 pPhysicalDevice->supportedSurfaces[pCreateInfo->surface] : NULL);
1553 if (!pSurface) {
1554 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1555 SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE,
1556 "%s() called with pCreateInfo->surface that "
1557 "was not returned by "
1558 "vkGetPhysicalDeviceSurfaceSupportKHR() "
1559 "for the device.",
1560 fn);
1561 }
Ian Elliott4f147fc2016-01-20 08:52:08 -07001562
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001563 // Validate pCreateInfo->minImageCount against
1564 // VkSurfaceCapabilitiesKHR::{min|max}ImageCount:
1565 VkSurfaceCapabilitiesKHR *pCapabilities = &pPhysicalDevice->surfaceCapabilities;
1566 if ((pCreateInfo->minImageCount < pCapabilities->minImageCount) ||
1567 ((pCapabilities->maxImageCount > 0) &&
1568 (pCreateInfo->minImageCount > pCapabilities->maxImageCount))) {
1569 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1570 SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT,
1571 "%s() called with pCreateInfo->minImageCount "
1572 "= %d, which is outside the bounds returned "
1573 "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. "
1574 "minImageCount = %d, maxImageCount = %d).",
1575 fn,
1576 pCreateInfo->minImageCount,
1577 pCapabilities->minImageCount,
1578 pCapabilities->maxImageCount);
1579 }
1580 // Validate pCreateInfo->imageExtent against
1581 // VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
1582 if ((pCapabilities->currentExtent.width == -1) &&
1583 ((pCreateInfo->imageExtent.width < pCapabilities->minImageExtent.width) ||
1584 (pCreateInfo->imageExtent.width > pCapabilities->maxImageExtent.width) ||
1585 (pCreateInfo->imageExtent.height < pCapabilities->minImageExtent.height) ||
1586 (pCreateInfo->imageExtent.height > pCapabilities->maxImageExtent.height))) {
1587 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1588 SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS,
1589 "%s() called with pCreateInfo->imageExtent = "
1590 "(%d,%d), which is outside the bounds "
1591 "returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): "
1592 "currentExtent = (%d,%d), minImageExtent = "
1593 "(%d,%d), maxImageExtent = (%d,%d).",
1594 fn,
1595 pCreateInfo->imageExtent.width,
1596 pCreateInfo->imageExtent.height,
1597 pCapabilities->currentExtent.width,
1598 pCapabilities->currentExtent.height,
1599 pCapabilities->minImageExtent.width,
1600 pCapabilities->minImageExtent.height,
1601 pCapabilities->maxImageExtent.width,
1602 pCapabilities->maxImageExtent.height);
1603 }
1604 if ((pCapabilities->currentExtent.width != -1) &&
1605 ((pCreateInfo->imageExtent.width != pCapabilities->currentExtent.width) ||
1606 (pCreateInfo->imageExtent.height != pCapabilities->currentExtent.height))) {
1607 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1608 SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN,
1609 "%s() called with pCreateInfo->imageExtent = "
1610 "(%d,%d), which is not equal to the "
1611 "currentExtent = (%d,%d) returned by "
1612 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1613 fn,
1614 pCreateInfo->imageExtent.width,
1615 pCreateInfo->imageExtent.height,
1616 pCapabilities->currentExtent.width,
1617 pCapabilities->currentExtent.height);
1618 }
1619 // Validate pCreateInfo->preTransform has one bit set (1st two
1620 // lines of if-statement), which bit is also set in
1621 // VkSurfaceCapabilitiesKHR::supportedTransforms (3rd line of if-statement):
1622 if (!pCreateInfo->preTransform ||
1623 (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) ||
1624 !(pCreateInfo->preTransform & pCapabilities->supportedTransforms)) {
1625 // This is an error situation; one for which we'd like to give
1626 // the developer a helpful, multi-line error message. Build it
1627 // up a little at a time, and then log it:
1628 std::string errorString = "";
1629 char str[1024];
1630 // Here's the first part of the message:
1631 sprintf(str, "%s() called with a non-supported "
1632 "pCreateInfo->preTransform (i.e. %s). "
1633 "Supported values are:\n",
1634 fn,
1635 surfaceTransformStr(pCreateInfo->preTransform));
1636 errorString += str;
1637 for (int i = 0; i < 32; i++) {
1638 // Build up the rest of the message:
1639 if ((1 << i) & pCapabilities->supportedTransforms) {
1640 const char *newStr =
1641 surfaceTransformStr((VkSurfaceTransformFlagBitsKHR) (1 << i));
1642 sprintf(str, " %s\n", newStr);
1643 errorString += str;
1644 }
1645 }
1646 // Log the message that we've built up:
1647 skipCall |= debug_report_log_msg(my_data->report_data,
1648 VK_DEBUG_REPORT_ERROR_BIT_EXT,
1649 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1650 (uint64_t) device, __LINE__,
1651 SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM,
1652 LAYER_NAME,
1653 errorString.c_str());
1654 }
1655 // Validate pCreateInfo->compositeAlpha has one bit set (1st two
1656 // lines of if-statement), which bit is also set in
1657 // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha (3rd line of if-statement):
1658 if (!pCreateInfo->compositeAlpha ||
1659 (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) ||
1660 !((pCreateInfo->compositeAlpha) & pCapabilities->supportedCompositeAlpha)) {
1661 // This is an error situation; one for which we'd like to give
1662 // the developer a helpful, multi-line error message. Build it
1663 // up a little at a time, and then log it:
1664 std::string errorString = "";
1665 char str[1024];
1666 // Here's the first part of the message:
1667 sprintf(str, "%s() called with a non-supported "
1668 "pCreateInfo->compositeAlpha (i.e. %s). "
1669 "Supported values are:\n",
1670 fn,
1671 surfaceCompositeAlphaStr(pCreateInfo->compositeAlpha));
1672 errorString += str;
1673 for (int i = 0; i < 32; i++) {
1674 // Build up the rest of the message:
1675 if ((1 << i) & pCapabilities->supportedCompositeAlpha) {
1676 const char *newStr =
1677 surfaceCompositeAlphaStr((VkCompositeAlphaFlagBitsKHR) (1 << i));
1678 sprintf(str, " %s\n", newStr);
1679 errorString += str;
1680 }
1681 }
1682 // Log the message that we've built up:
1683 skipCall |= debug_report_log_msg(my_data->report_data,
1684 VK_DEBUG_REPORT_ERROR_BIT_EXT,
1685 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1686 (uint64_t) device, 0,
1687 SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA,
1688 LAYER_NAME,
1689 errorString.c_str());
1690 }
1691 // Validate pCreateInfo->imageArraySize against
1692 // VkSurfaceCapabilitiesKHR::maxImageArraySize:
1693 if ((pCreateInfo->imageArrayLayers < 1) ||
1694 (pCreateInfo->imageArrayLayers > pCapabilities->maxImageArrayLayers)) {
1695 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1696 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_SIZE,
1697 "%s() called with a non-supported "
1698 "pCreateInfo->imageArraySize (i.e. %d). "
1699 "Minimum value is 1, maximum value is %d.",
1700 fn,
1701 pCreateInfo->imageArrayLayers,
1702 pCapabilities->maxImageArrayLayers);
1703 }
1704 // Validate pCreateInfo->imageUsage against
1705 // VkSurfaceCapabilitiesKHR::supportedUsageFlags:
1706 if (pCreateInfo->imageUsage !=
1707 (pCreateInfo->imageUsage & pCapabilities->supportedUsageFlags)) {
1708 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1709 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS,
1710 "%s() called with a non-supported "
1711 "pCreateInfo->imageUsage (i.e. 0x%08x)."
1712 " Supported flag bits are 0x%08x.",
1713 fn,
1714 pCreateInfo->imageUsage,
1715 pCapabilities->supportedUsageFlags);
1716 }
1717 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001718
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001719 // Validate pCreateInfo values with the results of
1720 // vkGetPhysicalDeviceSurfaceFormatsKHR():
1721 if (!pPhysicalDevice || !pPhysicalDevice->surfaceFormatCount) {
1722 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1723 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
1724 "%s() called before calling "
1725 "vkGetPhysicalDeviceSurfaceFormatsKHR().",
1726 fn);
1727 } else if (pCreateInfo) {
1728 // Validate pCreateInfo->imageFormat against
1729 // VkSurfaceFormatKHR::format:
1730 bool foundFormat = false;
1731 bool foundColorSpace = false;
1732 bool foundMatch = false;
1733 for (uint32_t i = 0 ; i < pPhysicalDevice->surfaceFormatCount ; i++) {
1734 if (pCreateInfo->imageFormat == pPhysicalDevice->pSurfaceFormats[i].format) {
1735 // Validate pCreateInfo->imageColorSpace against
1736 // VkSurfaceFormatKHR::colorSpace:
1737 foundFormat = true;
1738 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1739 foundMatch = true;
1740 break;
1741 }
1742 } else {
1743 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1744 foundColorSpace = true;
1745 }
1746 }
1747 }
1748 if (!foundMatch) {
1749 if (!foundFormat) {
1750 if (!foundColorSpace) {
1751 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device,
1752 "VkDevice",
1753 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP,
1754 "%s() called with neither a "
1755 "supported pCreateInfo->imageFormat "
1756 "(i.e. %d) nor a supported "
1757 "pCreateInfo->imageColorSpace "
1758 "(i.e. %d).",
1759 fn,
1760 pCreateInfo->imageFormat,
1761 pCreateInfo->imageColorSpace);
1762 } else {
1763 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device,
1764 "VkDevice",
1765 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT,
1766 "%s() called with a non-supported "
1767 "pCreateInfo->imageFormat (i.e. %d).",
1768 fn, pCreateInfo->imageFormat);
1769 }
1770 } else if (!foundColorSpace) {
1771 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1772 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE,
1773 "%s() called with a non-supported "
1774 "pCreateInfo->imageColorSpace (i.e. %d).",
1775 fn, pCreateInfo->imageColorSpace);
1776 }
1777 }
1778 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001779
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001780 // Validate pCreateInfo values with the results of
1781 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1782 if (!pPhysicalDevice || !pPhysicalDevice->presentModeCount) {
1783 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1784 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
1785 "%s() called before calling "
1786 "vkGetPhysicalDeviceSurfacePresentModesKHR().",
1787 fn);
1788 } else if (pCreateInfo) {
1789 // Validate pCreateInfo->presentMode against
1790 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1791 bool foundMatch = false;
1792 for (uint32_t i = 0 ; i < pPhysicalDevice->presentModeCount ; i++) {
1793 if (pPhysicalDevice->pPresentModes[i] == pCreateInfo->presentMode) {
1794 foundMatch = true;
1795 break;
1796 }
1797 }
1798 if (!foundMatch) {
1799 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1800 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE,
1801 "%s() called with a non-supported "
1802 "pCreateInfo->presentMode (i.e. %s).",
1803 fn,
1804 presentModeStr(pCreateInfo->presentMode));
1805 }
1806 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001807
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001808 // Validate pCreateInfo->imageSharingMode and related values:
1809 if (pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT) {
1810 if ((pCreateInfo->queueFamilyIndexCount <= 1) ||
1811 !pCreateInfo->pQueueFamilyIndices) {
1812 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1813 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_VALUES,
1814 "%s() called with a supported "
1815 "pCreateInfo->sharingMode of (i.e. %s),"
1816 "but with a bad value(s) for "
1817 "pCreateInfo->queueFamilyIndexCount or "
1818 "pCreateInfo->pQueueFamilyIndices).",
1819 fn,
1820 sharingModeStr(pCreateInfo->imageSharingMode));
1821 }
1822 } else if (pCreateInfo->imageSharingMode != VK_SHARING_MODE_EXCLUSIVE) {
1823 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1824 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_MODE,
1825 "%s() called with a non-supported "
1826 "pCreateInfo->imageSharingMode (i.e. %s).",
1827 fn,
1828 sharingModeStr(pCreateInfo->imageSharingMode));
1829 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001830
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001831 // Validate pCreateInfo->clipped:
1832 if (pCreateInfo &&
1833 (pCreateInfo->clipped != VK_FALSE) &&
1834 (pCreateInfo->clipped != VK_TRUE)) {
1835 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1836 device, "VkDevice",
1837 SWAPCHAIN_BAD_BOOL,
1838 "%s() called with a VkBool32 value that is "
1839 "neither VK_TRUE nor VK_FALSE, but has the "
1840 "numeric value of %d.",
1841 fn,
1842 pCreateInfo->clipped);
1843 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001844
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001845 // Validate pCreateInfo->oldSwapchain:
1846 if (pCreateInfo && pCreateInfo->oldSwapchain) {
1847 SwpSwapchain *pOldSwapchain = &my_data->swapchainMap[pCreateInfo->oldSwapchain];
1848 if (pOldSwapchain) {
1849 if (device != pOldSwapchain->pDevice->device) {
1850 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1851 device, "VkDevice",
1852 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
1853 "%s() called with a different VkDevice "
1854 "than the VkSwapchainKHR was created with.",
1855 __FUNCTION__);
1856 }
1857 if (pCreateInfo->surface != pOldSwapchain->pSurface->surface) {
1858 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1859 device, "VkDevice",
1860 SWAPCHAIN_CREATE_SWAP_DIFF_SURFACE,
1861 "%s() called with pCreateInfo->oldSwapchain "
1862 "that has a different VkSurfaceKHR than "
1863 "pCreateInfo->surface.",
1864 fn);
1865 }
1866 } else {
1867 // TBD: Leave this in (not sure object_track will check this)?
1868 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
1869 pCreateInfo->oldSwapchain,
1870 "VkSwapchainKHR");
1871 }
1872 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001873
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001874 return skipCall;
1875}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001876
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001877VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(
1878 VkDevice device,
1879 const VkSwapchainCreateInfoKHR* pCreateInfo,
1880 const VkAllocationCallbacks* pAllocator,
1881 VkSwapchainKHR* pSwapchain)
1882{
1883 VkResult result = VK_SUCCESS;
1884 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001885 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001886 VkBool32 skipCall = validateCreateSwapchainKHR(device, pCreateInfo,
1887 pSwapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001888
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001889 if (VK_FALSE == skipCall) {
1890 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -07001891 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001892 result = my_data->device_dispatch_table->CreateSwapchainKHR(
1893 device, pCreateInfo, pAllocator, pSwapchain);
Ian Elliott32311832016-02-04 08:17:18 -07001894 loader_platform_thread_lock_mutex(&globalLock);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001895
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001896 if (result == VK_SUCCESS) {
1897 // Remember the swapchain's handle, and link it to the device:
1898 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001899
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001900 my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
1901 if (pDevice) {
1902 pDevice->swapchains[*pSwapchain] =
1903 &my_data->swapchainMap[*pSwapchain];
1904 }
1905 my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
1906 my_data->swapchainMap[*pSwapchain].imageCount = 0;
1907 my_data->swapchainMap[*pSwapchain].usedAllocatorToCreate =
1908 (pAllocator != NULL);
1909 // Store a pointer to the surface
1910 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
1911 SwpInstance *pInstance =
1912 (pPhysicalDevice) ? pPhysicalDevice->pInstance : NULL;
1913 layer_data *my_instance_data =
1914 ((pInstance) ?
1915 get_my_data_ptr(get_dispatch_key(pInstance->instance), layer_data_map) :
1916 NULL);
1917 SwpSurface *pSurface =
1918 ((my_data && pCreateInfo) ?
1919 &my_instance_data->surfaceMap[pCreateInfo->surface] : NULL);
1920 my_data->swapchainMap[*pSwapchain].pSurface = pSurface;
1921 if (pSurface) {
1922 pSurface->swapchains[*pSwapchain] =
1923 &my_data->swapchainMap[*pSwapchain];
1924 }
1925 }
Ian Elliott32311832016-02-04 08:17:18 -07001926 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001927 return result;
1928 }
Ian Elliott32311832016-02-04 08:17:18 -07001929 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001930 return VK_ERROR_VALIDATION_FAILED_EXT;
1931}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001932
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001933VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR(
1934 VkDevice device,
1935 VkSwapchainKHR swapchain,
1936 const VkAllocationCallbacks* pAllocator)
1937{
1938// TODOs:
1939//
1940// - Implement a check for validity language that reads: All uses of
1941// presentable images acquired from pname:swapchain and owned by the
1942// application must: have completed execution
1943 VkBool32 skipCall = VK_FALSE;
1944 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001945 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001946 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott8b9e2562016-01-05 13:00:50 -07001947
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001948 // Validate that the swapchain extension was enabled:
1949 if (pDevice && !pDevice->swapchainExtensionEnabled) {
1950 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1951 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1952 "%s() called even though the %s extension was not enabled for this VkDevice.",
1953 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
1954 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001955
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001956 // Regardless of skipCall value, do some internal cleanup:
1957 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
1958 if (pSwapchain) {
1959 // Delete the SwpSwapchain associated with this swapchain:
1960 if (pSwapchain->pDevice) {
1961 pSwapchain->pDevice->swapchains.erase(swapchain);
1962 if (device != pSwapchain->pDevice->device) {
1963 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1964 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
1965 "%s() called with a different VkDevice than the "
1966 "VkSwapchainKHR was created with.",
1967 __FUNCTION__);
1968 }
1969 }
1970 if (pSwapchain->pSurface) {
1971 pSwapchain->pSurface->swapchains.erase(swapchain);
1972 }
1973 if (pSwapchain->imageCount) {
1974 pSwapchain->images.clear();
1975 }
1976 if ((pAllocator != NULL) != pSwapchain->usedAllocatorToCreate) {
1977 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance",
1978 SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
1979 "%s() called with incompatible pAllocator from when "
1980 "the object was created.",
1981 __FUNCTION__);
1982 }
1983 my_data->swapchainMap.erase(swapchain);
1984 }
Ian Elliott32311832016-02-04 08:17:18 -07001985 loader_platform_thread_unlock_mutex(&globalLock);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001986
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001987 if (VK_FALSE == skipCall) {
1988 // Call down the call chain:
1989 my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator);
1990 }
1991}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001992
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001993VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR(
1994 VkDevice device,
1995 VkSwapchainKHR swapchain,
1996 uint32_t* pSwapchainImageCount,
1997 VkImage* pSwapchainImages)
1998{
1999 VkResult result = VK_SUCCESS;
2000 VkBool32 skipCall = VK_FALSE;
2001 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07002002 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002003 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott8b9e2562016-01-05 13:00:50 -07002004
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002005 // Validate that the swapchain extension was enabled:
2006 if (pDevice && !pDevice->swapchainExtensionEnabled) {
2007 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
2008 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2009 "%s() called even though the %s extension was not enabled for this VkDevice.",
2010 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
2011 }
2012 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
2013 if (!pSwapchainImageCount) {
2014 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2015 device,
2016 "pSwapchainImageCount");
2017 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002018
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002019 if (VK_FALSE == skipCall) {
2020 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -07002021 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002022 result = my_data->device_dispatch_table->GetSwapchainImagesKHR(
2023 device, swapchain, pSwapchainImageCount, pSwapchainImages);
Ian Elliott32311832016-02-04 08:17:18 -07002024 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002025
Ian Elliott32311832016-02-04 08:17:18 -07002026 // Obtain this pointer again after locking:
2027 pSwapchain = &my_data->swapchainMap[swapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002028 if ((result == VK_SUCCESS) && pSwapchain && !pSwapchainImages &&
2029 pSwapchainImageCount) {
2030 // Record the result of this preliminary query:
2031 pSwapchain->imageCount = *pSwapchainImageCount;
2032 }
2033 else if ((result == VK_SUCCESS) && pSwapchain && pSwapchainImages &&
2034 pSwapchainImageCount) {
2035 // Compare the preliminary value of *pSwapchainImageCount with the
2036 // value this time:
2037 if (*pSwapchainImageCount > pSwapchain->imageCount) {
2038 LOG_ERROR_INVALID_COUNT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2039 device,
2040 "pSwapchainImageCount",
Ian Elliottf955d682015-12-30 12:00:54 -07002041 "pSwapchainImages",
Ian Elliottdcf8eca2016-01-05 14:28:32 -07002042 *pSwapchainImageCount,
Ian Elliottf955d682015-12-30 12:00:54 -07002043 pSwapchain->imageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002044 }
2045 else if (*pSwapchainImageCount > 0) {
2046 // Record the images and their state:
2047 pSwapchain->imageCount = *pSwapchainImageCount;
2048 for (uint32_t i = 0 ; i < *pSwapchainImageCount ; i++) {
2049 pSwapchain->images[i].image = pSwapchainImages[i];
2050 pSwapchain->images[i].pSwapchain = pSwapchain;
2051 pSwapchain->images[i].ownedByApp = false;
2052 }
2053 }
2054 }
Ian Elliott32311832016-02-04 08:17:18 -07002055 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002056 return result;
2057 }
Ian Elliott32311832016-02-04 08:17:18 -07002058 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002059 return VK_ERROR_VALIDATION_FAILED_EXT;
2060}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002061
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002062VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR(
2063 VkDevice device,
2064 VkSwapchainKHR swapchain,
2065 uint64_t timeout,
2066 VkSemaphore semaphore,
2067 VkFence fence,
2068 uint32_t* pImageIndex)
2069{
2070// TODOs:
2071//
2072// - Address the timeout. Possibilities include looking at the state of the
2073// swapchain's images, depending on the timeout value.
2074// - Implement a check for validity language that reads: If pname:semaphore is
2075// not sname:VK_NULL_HANDLE it must: be unsignalled
2076// - Implement a check for validity language that reads: If pname:fence is not
2077// sname:VK_NULL_HANDLE it must: be unsignalled and mustnot: be associated
2078// with any other queue command that has not yet completed execution on that
2079// queue
2080// - Record/update the state of the swapchain, in case an error occurs
2081// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
2082 VkResult result = VK_SUCCESS;
2083 VkBool32 skipCall = VK_FALSE;
2084 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07002085 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002086 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott8b9e2562016-01-05 13:00:50 -07002087
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002088 // Validate that the swapchain extension was enabled:
2089 if (pDevice && !pDevice->swapchainExtensionEnabled) {
2090 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
2091 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2092 "%s() called even though the %s extension was not enabled for this VkDevice.",
2093 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
2094 }
2095 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
2096 if (pSwapchain) {
2097 // Look to see if the application is trying to own too many images at
2098 // the same time (i.e. not leave any to display):
2099 uint32_t imagesOwnedByApp = 0;
2100 for (uint32_t i = 0 ; i < pSwapchain->imageCount ; i++) {
2101 if (pSwapchain->images[i].ownedByApp) {
2102 imagesOwnedByApp++;
2103 }
2104 }
2105 if (imagesOwnedByApp >= (pSwapchain->imageCount - 1)) {
2106 skipCall |= LOG_PERF_WARNING(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
2107 swapchain,
2108 "VkSwapchainKHR",
2109 SWAPCHAIN_APP_OWNS_TOO_MANY_IMAGES,
2110 "%s() called when the application "
2111 "already owns all presentable images "
2112 "in this swapchain except for the "
2113 "image currently being displayed. "
2114 "This call to %s() cannot succeed "
2115 "unless another thread calls the "
2116 "vkQueuePresentKHR() function in "
2117 "order to release ownership of one of "
2118 "the presentable images of this "
2119 "swapchain.",
2120 __FUNCTION__, __FUNCTION__);
2121 }
2122 }
2123 if (!pImageIndex) {
2124 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2125 device,
2126 "pImageIndex");
2127 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002128
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002129 if (VK_FALSE == skipCall) {
2130 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -07002131 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002132 result = my_data->device_dispatch_table->AcquireNextImageKHR(
2133 device, swapchain, timeout, semaphore, fence, pImageIndex);
Ian Elliott32311832016-02-04 08:17:18 -07002134 loader_platform_thread_lock_mutex(&globalLock);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002135
Ian Elliott32311832016-02-04 08:17:18 -07002136 // Obtain this pointer again after locking:
2137 pSwapchain = &my_data->swapchainMap[swapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002138 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) &&
2139 pSwapchain) {
2140 // Change the state of the image (now owned by the application):
2141 pSwapchain->images[*pImageIndex].ownedByApp = true;
2142 }
Ian Elliott32311832016-02-04 08:17:18 -07002143 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002144 return result;
2145 }
Ian Elliott32311832016-02-04 08:17:18 -07002146 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002147 return VK_ERROR_VALIDATION_FAILED_EXT;
2148}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002149
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002150VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(
2151 VkQueue queue,
2152 const VkPresentInfoKHR* pPresentInfo)
2153{
2154// TODOs:
2155//
2156// - Implement a check for validity language that reads: Any given element of
2157// sname:VkSemaphore in pname:pWaitSemaphores must: refer to a prior signal
2158// of that sname:VkSemaphore that won't be consumed by any other wait on that
2159// semaphore
2160// - Record/update the state of the swapchain, in case an error occurs
2161// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
2162 VkResult result = VK_SUCCESS;
2163 VkBool32 skipCall = VK_FALSE;
2164 layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002165
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002166 if (!pPresentInfo) {
2167 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2168 device,
2169 "pPresentInfo");
2170 } else {
2171 if (pPresentInfo->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR) {
2172 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2173 device,
2174 "pPresentInfo",
2175 "VK_STRUCTURE_TYPE_PRESENT_INFO_KHR");
2176 }
2177 if (pPresentInfo->pNext != NULL) {
2178 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2179 device,
2180 "pPresentInfo");
2181 }
2182 if (!pPresentInfo->swapchainCount) {
2183 skipCall |= LOG_ERROR_ZERO_VALUE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2184 device,
2185 "pPresentInfo->swapchainCount");
2186 }
2187 if (!pPresentInfo->pSwapchains) {
2188 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2189 device,
2190 "pPresentInfo->pSwapchains");
2191 }
2192 if (!pPresentInfo->pImageIndices) {
2193 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2194 device,
2195 "pPresentInfo->pImageIndices");
2196 }
2197 // Note: pPresentInfo->pResults is allowed to be NULL
2198 }
Ian Elliott046ed2c2015-12-30 17:07:17 -07002199
Ian Elliott32311832016-02-04 08:17:18 -07002200 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002201 for (uint32_t i = 0;
2202 pPresentInfo && (i < pPresentInfo->swapchainCount);
2203 i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002204 uint32_t index = pPresentInfo->pImageIndices[i];
2205 SwpSwapchain *pSwapchain =
2206 &my_data->swapchainMap[pPresentInfo->pSwapchains[i]];
2207 if (pSwapchain) {
2208 if (!pSwapchain->pDevice->swapchainExtensionEnabled) {
2209 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2210 pSwapchain->pDevice, "VkDevice",
2211 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2212 "%s() called even though the %s extension was not enabled for this VkDevice.",
2213 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
2214 }
2215 if (index >= pSwapchain->imageCount) {
2216 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
2217 pPresentInfo->pSwapchains[i],
2218 "VkSwapchainKHR",
2219 SWAPCHAIN_INDEX_TOO_LARGE,
2220 "%s() called for an index that is too "
2221 "large (i.e. %d). There are only %d "
2222 "images in this VkSwapchainKHR.\n",
2223 __FUNCTION__, index,
2224 pSwapchain->imageCount);
2225 } else {
2226 if (!pSwapchain->images[index].ownedByApp) {
2227 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
2228 pPresentInfo->pSwapchains[i],
2229 "VkSwapchainKHR",
2230 SWAPCHAIN_INDEX_NOT_IN_USE,
2231 "%s() returned an index (i.e. %d) "
2232 "for an image that is not owned by "
2233 "the application.",
2234 __FUNCTION__, index);
2235 }
2236 }
2237 SwpQueue *pQueue = &my_data->queueMap[queue];
2238 SwpSurface *pSurface = pSwapchain->pSurface;
2239 if (pQueue && pSurface && pSurface->numQueueFamilyIndexSupport) {
2240 uint32_t queueFamilyIndex = pQueue->queueFamilyIndex;
2241 // Note: the 1st test is to ensure queueFamilyIndex is in range,
2242 // and the 2nd test is the validation check:
2243 if ((pSurface->numQueueFamilyIndexSupport > queueFamilyIndex) &&
2244 (!pSurface->pQueueFamilyIndexSupport[queueFamilyIndex])) {
2245 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
2246 pPresentInfo->pSwapchains[i],
2247 "VkSwapchainKHR",
2248 SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE,
2249 "%s() called with a swapchain whose "
2250 "surface is not supported for "
2251 "presention on this device with the "
2252 "queueFamilyIndex (i.e. %d) of the "
2253 "given queue.",
2254 __FUNCTION__, queueFamilyIndex);
2255 }
2256 }
2257 }
2258 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002259
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002260 if (VK_FALSE == skipCall) {
2261 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -07002262 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002263 result = my_data->device_dispatch_table->QueuePresentKHR(queue,
2264 pPresentInfo);
Ian Elliott32311832016-02-04 08:17:18 -07002265 loader_platform_thread_lock_mutex(&globalLock);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002266
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002267 if (pPresentInfo &&
2268 ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR))) {
2269 for (uint32_t i = 0; i < pPresentInfo->swapchainCount ; i++) {
2270 int index = pPresentInfo->pImageIndices[i];
2271 SwpSwapchain *pSwapchain =
2272 &my_data->swapchainMap[pPresentInfo->pSwapchains[i]];
2273 if (pSwapchain) {
2274 // Change the state of the image (no longer owned by the
2275 // application):
2276 pSwapchain->images[index].ownedByApp = false;
2277 }
2278 }
2279 }
Ian Elliott32311832016-02-04 08:17:18 -07002280 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002281 return result;
2282 }
Ian Elliott32311832016-02-04 08:17:18 -07002283 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002284 return VK_ERROR_VALIDATION_FAILED_EXT;
2285}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002286
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002287VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue(
2288 VkDevice device,
2289 uint32_t queueFamilyIndex,
2290 uint32_t queueIndex,
2291 VkQueue* pQueue)
2292{
2293 VkBool32 skipCall = VK_FALSE;
2294 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliottc4db6952016-01-21 14:29:45 -07002295
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002296 if (VK_FALSE == skipCall) {
2297 // Call down the call chain:
2298 my_data->device_dispatch_table->GetDeviceQueue(
2299 device, queueFamilyIndex, queueIndex, pQueue);
Ian Elliottc4db6952016-01-21 14:29:45 -07002300
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002301 // Remember the queue's handle, and link it to the device:
Ian Elliott32311832016-02-04 08:17:18 -07002302 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002303 SwpDevice *pDevice = &my_data->deviceMap[device];
2304 my_data->queueMap[&pQueue].queue = *pQueue;
2305 if (pDevice) {
2306 pDevice->queues[*pQueue] = &my_data->queueMap[*pQueue];
2307 }
2308 my_data->queueMap[&pQueue].pDevice = pDevice;
2309 my_data->queueMap[&pQueue].queueFamilyIndex = queueFamilyIndex;
Ian Elliott32311832016-02-04 08:17:18 -07002310 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002311 }
2312}
Ian Elliottc4db6952016-01-21 14:29:45 -07002313
2314
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002315VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(
2316 VkInstance instance,
2317 const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
2318 const VkAllocationCallbacks* pAllocator,
2319 VkDebugReportCallbackEXT* pMsgCallback)
2320{
2321 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2322 VkResult result = my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
2323 if (VK_SUCCESS == result) {
Ian Elliott32311832016-02-04 08:17:18 -07002324 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002325 result = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback);
Ian Elliott32311832016-02-04 08:17:18 -07002326 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002327 }
2328 return result;
2329}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002330
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002331VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, const VkAllocationCallbacks *pAllocator)
2332{
2333 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2334 my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Ian Elliott32311832016-02-04 08:17:18 -07002335 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002336 layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
Ian Elliott32311832016-02-04 08:17:18 -07002337 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002338}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002339
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002340VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(
2341 VkInstance instance,
2342 VkDebugReportFlagsEXT flags,
2343 VkDebugReportObjectTypeEXT objType,
2344 uint64_t object,
2345 size_t location,
2346 int32_t msgCode,
2347 const char* pLayerPrefix,
2348 const char* pMsg)
2349{
2350 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2351 my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
2352}
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07002353
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002354VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)
2355{
2356 if (!strcmp("vkGetDeviceProcAddr", funcName))
2357 return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
2358 if (!strcmp(funcName, "vkDestroyDevice"))
2359 return (PFN_vkVoidFunction) vkDestroyDevice;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002360
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002361 if (device == VK_NULL_HANDLE) {
2362 return NULL;
2363 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002364
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002365 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06002366
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002367 my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2368 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
2369 if (my_data->deviceMap.size() != 0 &&
2370 my_data->deviceMap[device].swapchainExtensionEnabled)
2371 {
2372 if (!strcmp("vkCreateSwapchainKHR", funcName))
2373 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateSwapchainKHR);
2374 if (!strcmp("vkDestroySwapchainKHR", funcName))
2375 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySwapchainKHR);
2376 if (!strcmp("vkGetSwapchainImagesKHR", funcName))
2377 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSwapchainImagesKHR);
2378 if (!strcmp("vkAcquireNextImageKHR", funcName))
2379 return reinterpret_cast<PFN_vkVoidFunction>(vkAcquireNextImageKHR);
2380 if (!strcmp("vkQueuePresentKHR", funcName))
2381 return reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR);
2382 }
2383 if (!strcmp("vkGetDeviceQueue", funcName))
2384 return reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceQueue);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002385
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002386 if (pDisp->GetDeviceProcAddr == NULL)
2387 return NULL;
2388 return pDisp->GetDeviceProcAddr(device, funcName);
2389}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002390
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002391VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
2392{
2393 if (!strcmp("vkGetInstanceProcAddr", funcName))
2394 return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
2395 if (!strcmp(funcName, "vkCreateInstance"))
2396 return (PFN_vkVoidFunction) vkCreateInstance;
2397 if (!strcmp(funcName, "vkDestroyInstance"))
2398 return (PFN_vkVoidFunction) vkDestroyInstance;
2399 if (!strcmp(funcName, "vkCreateDevice"))
2400 return (PFN_vkVoidFunction) vkCreateDevice;
2401 if (!strcmp(funcName, "vkEnumeratePhysicalDevices"))
2402 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
2403 if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
2404 return (PFN_vkVoidFunction) vkEnumerateInstanceLayerProperties;
2405 if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
2406 return (PFN_vkVoidFunction) vkEnumerateInstanceExtensionProperties;
2407 if (!strcmp(funcName, "vkGetPhysicalDeviceQueueFamilyProperties"))
2408 return (PFN_vkVoidFunction) vkGetPhysicalDeviceQueueFamilyProperties;
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07002409
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002410 if (instance == VK_NULL_HANDLE) {
2411 return NULL;
2412 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002413
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002414 PFN_vkVoidFunction addr;
2415
2416 layer_data *my_data;
2417 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2418 VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
2419 addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
2420 if (addr) {
2421 return addr;
2422 }
Ian Elliott68124ac2015-10-07 16:18:35 -06002423
Ian Elliotta983e9a2015-12-22 12:18:12 -07002424#ifdef VK_USE_PLATFORM_ANDROID_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002425 if (my_data->instanceMap.size() != 0 &&
2426 my_data->instanceMap[instance].androidSurfaceExtensionEnabled)
2427 {
2428 if (!strcmp("vkCreateAndroidSurfaceKHR", funcName))
2429 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateAndroidSurfaceKHR);
2430 }
Ian Elliotta983e9a2015-12-22 12:18:12 -07002431#endif // VK_USE_PLATFORM_ANDROID_KHR
2432#ifdef VK_USE_PLATFORM_MIR_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002433 if (my_data->instanceMap.size() != 0 &&
2434 my_data->instanceMap[instance].mirSurfaceExtensionEnabled)
2435 {
2436 if (!strcmp("vkCreateMirSurfaceKHR", funcName))
2437 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateMirSurfaceKHR);
2438 if (!strcmp("vkGetPhysicalDeviceMirPresentationSupportKHR", funcName))
2439 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceMirPresentationSupportKHR);
2440 }
Ian Elliotta983e9a2015-12-22 12:18:12 -07002441#endif // VK_USE_PLATFORM_MIR_KHR
2442#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002443 if (my_data->instanceMap.size() != 0 &&
2444 my_data->instanceMap[instance].waylandSurfaceExtensionEnabled)
2445 {
2446 if (!strcmp("vkCreateWaylandSurfaceKHR", funcName))
2447 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateWaylandSurfaceKHR);
2448 if (!strcmp("vkGetPhysicalDeviceWaylandPresentationSupportKHR", funcName))
2449 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceWaylandPresentationSupportKHR);
2450 }
Ian Elliotta983e9a2015-12-22 12:18:12 -07002451#endif // VK_USE_PLATFORM_WAYLAND_KHR
2452#ifdef VK_USE_PLATFORM_WIN32_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002453 if (my_data->instanceMap.size() != 0 &&
2454 my_data->instanceMap[instance].win32SurfaceExtensionEnabled)
2455 {
2456 if (!strcmp("vkCreateWin32SurfaceKHR", funcName))
2457 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateWin32SurfaceKHR);
2458 if (!strcmp("vkGetPhysicalDeviceWin32PresentationSupportKHR", funcName))
2459 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceWin32PresentationSupportKHR);
2460 }
Ian Elliotta983e9a2015-12-22 12:18:12 -07002461#endif // VK_USE_PLATFORM_WIN32_KHR
2462#ifdef VK_USE_PLATFORM_XCB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002463 if (my_data->instanceMap.size() != 0 &&
2464 my_data->instanceMap[instance].xcbSurfaceExtensionEnabled)
2465 {
2466 if (!strcmp("vkCreateXcbSurfaceKHR", funcName))
2467 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateXcbSurfaceKHR);
2468 if (!strcmp("vkGetPhysicalDeviceXcbPresentationSupportKHR", funcName))
2469 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceXcbPresentationSupportKHR);
2470 }
Ian Elliotta983e9a2015-12-22 12:18:12 -07002471#endif // VK_USE_PLATFORM_XCB_KHR
2472#ifdef VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002473 if (my_data->instanceMap.size() != 0 &&
2474 my_data->instanceMap[instance].xlibSurfaceExtensionEnabled)
2475 {
2476 if (!strcmp("vkCreateXlibSurfaceKHR", funcName))
2477 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateXlibSurfaceKHR);
2478 if (!strcmp("vkGetPhysicalDeviceXlibPresentationSupportKHR", funcName))
2479 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceXlibPresentationSupportKHR);
2480 }
Ian Elliotta983e9a2015-12-22 12:18:12 -07002481#endif // VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002482 if (my_data->instanceMap.size() != 0 &&
2483 my_data->instanceMap[instance].surfaceExtensionEnabled)
2484 {
2485 if (!strcmp("vkDestroySurfaceKHR", funcName))
2486 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySurfaceKHR);
2487 if (!strcmp("vkGetPhysicalDeviceSurfaceSupportKHR", funcName))
2488 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceSupportKHR);
2489 if (!strcmp("vkGetPhysicalDeviceSurfaceCapabilitiesKHR", funcName))
2490 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
2491 if (!strcmp("vkGetPhysicalDeviceSurfaceFormatsKHR", funcName))
2492 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceFormatsKHR);
2493 if (!strcmp("vkGetPhysicalDeviceSurfacePresentModesKHR", funcName))
2494 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfacePresentModesKHR);
2495 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002496
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002497 if (pTable->GetInstanceProcAddr == NULL)
2498 return NULL;
2499 return pTable->GetInstanceProcAddr(instance, funcName);
2500}
2501