blob: e4a00c34e2f7adeff479b7fcb11d31f5b250fb5e [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{
Courtney Goeltzenleuchterbeb42f82016-02-12 13:46:04 -070059 return util_GetExtensionProperties(ARRAY_SIZE(instance_extensions),
60 instance_extensions, pCount,
61 pProperties);
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -070062}
63
Courtney Goeltzenleuchterbeb42f82016-02-12 13:46:04 -070064VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
65vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
66 const char *pLayerName, uint32_t *pCount,
67 VkExtensionProperties *pProperties) {
68 if (pLayerName == NULL) {
69 dispatch_key key = get_dispatch_key(physicalDevice);
70 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
71 return my_data->instance_dispatch_table
72 ->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount,
73 pProperties);
74 } else {
75 return util_GetExtensionProperties(0, nullptr, pCount, pProperties);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070076 }
Courtney Goeltzenleuchterbeb42f82016-02-12 13:46:04 -070077}
78
79static const VkLayerProperties swapchain_layers[] = {{
80 "VK_LAYER_LUNARG_swapchain", VK_API_VERSION, 1, "LunarG Validation Layer",
81}};
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -070082
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070083VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
84 uint32_t *pCount,
85 VkLayerProperties* pProperties)
86{
Courtney Goeltzenleuchterbeb42f82016-02-12 13:46:04 -070087 return util_GetLayerProperties(ARRAY_SIZE(swapchain_layers),
88 swapchain_layers, pCount, pProperties);
89}
90
91VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(
92 VkPhysicalDevice physicalDevice, uint32_t *pCount,
93 VkLayerProperties *pProperties) {
94 return util_GetLayerProperties(ARRAY_SIZE(swapchain_layers),
95 swapchain_layers, pCount, pProperties);
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -070096}
97
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070098static void createDeviceRegisterExtensions(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, VkDevice device)
99{
Ian Elliott0b4d6242015-09-22 10:51:24 -0600100 uint32_t i;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700101 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
102 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600103
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700104 VkLayerDispatchTable *pDisp = my_device_data->device_dispatch_table;
105 PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr;
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700106
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700107 pDisp->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR) gpa(device, "vkCreateSwapchainKHR");
108 pDisp->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR) gpa(device, "vkDestroySwapchainKHR");
109 pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR) gpa(device, "vkGetSwapchainImagesKHR");
110 pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR) gpa(device, "vkAcquireNextImageKHR");
111 pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR) gpa(device, "vkQueuePresentKHR");
112 pDisp->GetDeviceQueue = (PFN_vkGetDeviceQueue) gpa(device, "vkGetDeviceQueue");
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700113
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700114 SwpPhysicalDevice *pPhysicalDevice = &my_instance_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600115 if (pPhysicalDevice) {
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700116 my_device_data->deviceMap[device].pPhysicalDevice = pPhysicalDevice;
117 pPhysicalDevice->pDevice = &my_device_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600118 } else {
Ian Elliott07adb112016-01-05 12:51:03 -0700119 // TBD: Should we leave error in (since Swapchain really needs this
120 // link)?
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700121 log_msg(my_instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
122 (uint64_t)physicalDevice , __LINE__, SWAPCHAIN_INVALID_HANDLE, "Swapchain",
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700123 "vkCreateDevice() called with a non-valid VkPhysicalDevice.");
Ian Elliott0b4d6242015-09-22 10:51:24 -0600124 }
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700125 my_device_data->deviceMap[device].device = device;
Ian Elliott427058f2015-12-29 16:45:49 -0700126 my_device_data->deviceMap[device].swapchainExtensionEnabled = false;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600127
128 // Record whether the WSI device extension was enabled for this VkDevice.
129 // No need to check if the extension was advertised by
130 // vkEnumerateDeviceExtensionProperties(), since the loader handles that.
Jon Ashburnf19916e2016-01-11 13:12:43 -0700131 for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700132 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600133
Ian Elliott427058f2015-12-29 16:45:49 -0700134 my_device_data->deviceMap[device].swapchainExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600135 }
136 }
137}
138
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700139static void createInstanceRegisterExtensions(const VkInstanceCreateInfo* pCreateInfo, VkInstance instance)
140{
Ian Elliott0b4d6242015-09-22 10:51:24 -0600141 uint32_t i;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700142 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
143 VkLayerInstanceDispatchTable *pDisp = my_data->instance_dispatch_table;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600144 PFN_vkGetInstanceProcAddr gpa = pDisp->GetInstanceProcAddr;
Ian Elliotta983e9a2015-12-22 12:18:12 -0700145#ifdef VK_USE_PLATFORM_ANDROID_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700146 pDisp->CreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR) gpa(instance, "vkCreateAndroidSurfaceKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -0700147#endif // VK_USE_PLATFORM_ANDROID_KHR
148#ifdef VK_USE_PLATFORM_MIR_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700149 pDisp->CreateMirSurfaceKHR = (PFN_vkCreateMirSurfaceKHR) gpa(instance, "vkCreateMirSurfaceKHR");
150 pDisp->GetPhysicalDeviceMirPresentationSupportKHR = (PFN_vkGetPhysicalDeviceMirPresentationSupportKHR) gpa(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -0700151#endif // VK_USE_PLATFORM_MIR_KHR
152#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700153 pDisp->CreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR) gpa(instance, "vkCreateWaylandSurfaceKHR");
154 pDisp->GetPhysicalDeviceWaylandPresentationSupportKHR = (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR) gpa(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -0700155#endif // VK_USE_PLATFORM_WAYLAND_KHR
156#ifdef VK_USE_PLATFORM_WIN32_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700157 pDisp->CreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR) gpa(instance, "vkCreateWin32SurfaceKHR");
158 pDisp->GetPhysicalDeviceWin32PresentationSupportKHR = (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR) gpa(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -0700159#endif // VK_USE_PLATFORM_WIN32_KHR
160#ifdef VK_USE_PLATFORM_XCB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700161 pDisp->CreateXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR) gpa(instance, "vkCreateXcbSurfaceKHR");
162 pDisp->GetPhysicalDeviceXcbPresentationSupportKHR = (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR) gpa(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -0700163#endif // VK_USE_PLATFORM_XCB_KHR
164#ifdef VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700165 pDisp->CreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR) gpa(instance, "vkCreateXlibSurfaceKHR");
166 pDisp->GetPhysicalDeviceXlibPresentationSupportKHR = (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR) gpa(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -0700167#endif // VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700168 pDisp->DestroySurfaceKHR = (PFN_vkDestroySurfaceKHR) gpa(instance, "vkDestroySurfaceKHR");
169 pDisp->GetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceSupportKHR");
170 pDisp->GetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
171 pDisp->GetPhysicalDeviceSurfaceFormatsKHR = (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR");
172 pDisp->GetPhysicalDeviceSurfacePresentModesKHR = (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR) gpa(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR");
Ian Elliott0b4d6242015-09-22 10:51:24 -0600173
Ian Elliott1dcd1092015-11-17 17:29:40 -0700174 // Remember this instance, and whether the VK_KHR_surface extension
Ian Elliott0b4d6242015-09-22 10:51:24 -0600175 // was enabled for it:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600176 my_data->instanceMap[instance].instance = instance;
Ian Elliott1cb77a62015-12-29 16:44:39 -0700177 my_data->instanceMap[instance].surfaceExtensionEnabled = false;
Ian Elliott8dffaf32016-01-04 14:10:30 -0700178#ifdef VK_USE_PLATFORM_ANDROID_KHR
179 my_data->instanceMap[instance].androidSurfaceExtensionEnabled = false;
180#endif // VK_USE_PLATFORM_ANDROID_KHR
181#ifdef VK_USE_PLATFORM_MIR_KHR
182 my_data->instanceMap[instance].mirSurfaceExtensionEnabled = false;
183#endif // VK_USE_PLATFORM_MIR_KHR
184#ifdef VK_USE_PLATFORM_WAYLAND_KHR
185 my_data->instanceMap[instance].waylandSurfaceExtensionEnabled = false;
186#endif // VK_USE_PLATFORM_WAYLAND_KHR
187#ifdef VK_USE_PLATFORM_WIN32_KHR
188 my_data->instanceMap[instance].win32SurfaceExtensionEnabled = false;
189#endif // VK_USE_PLATFORM_WIN32_KHR
190#ifdef VK_USE_PLATFORM_XCB_KHR
191 my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = false;
192#endif // VK_USE_PLATFORM_XCB_KHR
193#ifdef VK_USE_PLATFORM_XLIB_KHR
194 my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = false;
195#endif // VK_USE_PLATFORM_XLIB_KHR
196
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700197
Ian Elliott0b4d6242015-09-22 10:51:24 -0600198 // Record whether the WSI instance extension was enabled for this
199 // VkInstance. No need to check if the extension was advertised by
200 // vkEnumerateInstanceExtensionProperties(), since the loader handles that.
Jon Ashburnf19916e2016-01-11 13:12:43 -0700201 for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700202 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600203
Ian Elliott1cb77a62015-12-29 16:44:39 -0700204 my_data->instanceMap[instance].surfaceExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600205 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700206#ifdef VK_USE_PLATFORM_ANDROID_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700207 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700208
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800209 my_data->instanceMap[instance].androidSurfaceExtensionEnabled =
210 true;
211 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700212#endif // VK_USE_PLATFORM_ANDROID_KHR
213#ifdef VK_USE_PLATFORM_MIR_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700214 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_MIR_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700215
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700216 my_data->instanceMap[instance].mirSurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800217 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700218#endif // VK_USE_PLATFORM_MIR_KHR
219#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700220 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700221
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800222 my_data->instanceMap[instance].waylandSurfaceExtensionEnabled =
223 true;
224 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700225#endif // VK_USE_PLATFORM_WAYLAND_KHR
226#ifdef VK_USE_PLATFORM_WIN32_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700227 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700228
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700229 my_data->instanceMap[instance].win32SurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800230 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700231#endif // VK_USE_PLATFORM_WIN32_KHR
232#ifdef VK_USE_PLATFORM_XCB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700233 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700234
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700235 my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800236 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700237#endif // VK_USE_PLATFORM_XCB_KHR
238#ifdef VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700239 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700240
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700241 my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = true;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700242 }
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800243#endif // VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700244 }
245}
246
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700247#include "vk_dispatch_table_helper.h"
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700248static void initSwapchain(layer_data *my_data, const VkAllocationCallbacks *pAllocator)
249{
250 uint32_t report_flags = 0;
251 uint32_t debug_action = 0;
252 FILE *log_output = NULL;
253 const char *option_str;
254 VkDebugReportCallbackEXT callback;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600255
Mark Lobodzinski8cbde242016-02-23 09:58:39 -0700256 // Initialize swapchain options:
257 report_flags = getLayerOptionFlags("lunarg_swapchain.report_flags", 0);
258 getLayerOptionEnum("lunarg_swapchain.debug_action", (uint32_t *) &debug_action);
Ian Elliott07adb112016-01-05 12:51:03 -0700259
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700260 if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)
261 {
262 // Turn on logging, since it was requested:
Mark Lobodzinski8cbde242016-02-23 09:58:39 -0700263 option_str = getLayerOption("lunarg_swapchain.log_filename");
264 log_output = getLayerLogOutput(option_str, "lunarg_swapchain");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700265 VkDebugReportCallbackCreateInfoEXT dbgInfo;
266 memset(&dbgInfo, 0, sizeof(dbgInfo));
267 dbgInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
268 dbgInfo.pfnCallback = log_callback;
269 dbgInfo.pUserData = log_output;
270 dbgInfo.flags = report_flags;
271 layer_create_msg_callback(my_data->report_data,
272 &dbgInfo,
273 pAllocator,
274 &callback);
275 my_data->logging_callback.push_back(callback);
276 }
277 if (debug_action & VK_DBG_LAYER_ACTION_DEBUG_OUTPUT) {
278 VkDebugReportCallbackCreateInfoEXT dbgInfo;
279 memset(&dbgInfo, 0, sizeof(dbgInfo));
280 dbgInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
281 dbgInfo.pfnCallback = win32_debug_output_msg;
282 dbgInfo.pUserData = log_output;
283 dbgInfo.flags = report_flags;
284 layer_create_msg_callback(my_data->report_data, &dbgInfo, pAllocator, &callback);
285 my_data->logging_callback.push_back(callback);
286 }
Ian Elliott32311832016-02-04 08:17:18 -0700287 if (!globalLockInitialized)
288 {
289 loader_platform_thread_create_mutex(&globalLock);
290 globalLockInitialized = 1;
291 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700292}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600293
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700294static const char *surfaceTransformStr(VkSurfaceTransformFlagBitsKHR value)
295{
296 // Return a string corresponding to the value:
297 return string_VkSurfaceTransformFlagBitsKHR(value);
298}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600299
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700300static const char *surfaceCompositeAlphaStr(VkCompositeAlphaFlagBitsKHR value)
301{
302 // Return a string corresponding to the value:
303 return string_VkCompositeAlphaFlagBitsKHR(value);
304}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600305
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700306static const char *presentModeStr(VkPresentModeKHR value)
307{
308 // Return a string corresponding to the value:
309 return string_VkPresentModeKHR(value);
310}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600311
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700312static const char *sharingModeStr(VkSharingMode value)
313{
314 // Return a string corresponding to the value:
315 return string_VkSharingMode(value);
316}
Ian Elliott07adb112016-01-05 12:51:03 -0700317
Ian Elliott0b4d6242015-09-22 10:51:24 -0600318
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700319VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance)
320{
321 VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600322
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700323 assert(chain_info->u.pLayerInfo);
324 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
325 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");
326 if (fpCreateInstance == NULL) {
327 return VK_ERROR_INITIALIZATION_FAILED;
328 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700329
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700330 // Advance the link info for the next element on the chain
331 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700332
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700333 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
334 if (result != VK_SUCCESS) {
335 return result;
336 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700337
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700338 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
339 my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
340 layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700341
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700342 my_data->report_data = debug_report_create_instance(
343 my_data->instance_dispatch_table,
344 *pInstance,
345 pCreateInfo->enabledExtensionCount,
346 pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700347
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700348 // Call the following function after my_data is initialized:
349 createInstanceRegisterExtensions(pCreateInfo, *pInstance);
350 initSwapchain(my_data, pAllocator);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700351
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700352 return result;
353}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700354
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700355VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator)
356{
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700357 dispatch_key key = get_dispatch_key(instance);
358 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
359 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700360
Ian Elliott32311832016-02-04 08:17:18 -0700361 // Call down the call chain:
362 my_data->instance_dispatch_table->DestroyInstance(instance, pAllocator);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700363
Ian Elliott32311832016-02-04 08:17:18 -0700364 loader_platform_thread_lock_mutex(&globalLock);
365
Ian Elliott32311832016-02-04 08:17:18 -0700366 // Do additional internal cleanup:
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700367 if (pInstance) {
368 // Delete all of the SwpPhysicalDevice's, SwpSurface's, and the
369 // SwpInstance associated with this instance:
370 for (auto it = pInstance->physicalDevices.begin() ;
371 it != pInstance->physicalDevices.end() ; it++) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700372
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700373 // Free memory that was allocated for/by this SwpPhysicalDevice:
374 SwpPhysicalDevice *pPhysicalDevice = it->second;
375 if (pPhysicalDevice) {
Ian Elliott458696a2016-02-04 06:11:17 -0700376 if (pPhysicalDevice->pDevice) {
377 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance",
378 SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
379 "%s() called before all of its associated "
380 "VkDevices were destroyed.",
381 __FUNCTION__);
382 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700383 free(pPhysicalDevice->pSurfaceFormats);
384 free(pPhysicalDevice->pPresentModes);
385 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700386
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700387 // Erase the SwpPhysicalDevice's from the my_data->physicalDeviceMap (which
388 // are simply pointed to by the SwpInstance):
389 my_data->physicalDeviceMap.erase(it->second->physicalDevice);
390 }
391 for (auto it = pInstance->surfaces.begin() ;
392 it != pInstance->surfaces.end() ; it++) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700393
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700394 // Free memory that was allocated for/by this SwpPhysicalDevice:
395 SwpSurface *pSurface = it->second;
396 if (pSurface) {
397 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance",
398 SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
399 "%s() called before all of its associated "
400 "VkSurfaceKHRs were destroyed.",
401 __FUNCTION__);
402 }
403 }
404 my_data->instanceMap.erase(instance);
405 }
Mark Lobodzinski3c99d552016-02-04 13:50:23 -0700406
407 // Clean up logging callback, if any
408 while (my_data->logging_callback.size() > 0) {
409 VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
410 layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
411 my_data->logging_callback.pop_back();
412 }
413 layer_debug_report_destroy_instance(my_data->report_data);
414
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700415 delete my_data->instance_dispatch_table;
416 layer_data_map.erase(key);
Ian Elliott32311832016-02-04 08:17:18 -0700417 if (layer_data_map.empty()) {
418 // Release mutex when destroying last instance
419 loader_platform_thread_unlock_mutex(&globalLock);
420 loader_platform_thread_delete_mutex(&globalLock);
421 globalLockInitialized = 0;
422 } else {
423 loader_platform_thread_unlock_mutex(&globalLock);
424 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700425}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700426
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700427VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties(
428 VkPhysicalDevice physicalDevice,
429 uint32_t* pQueueFamilyPropertyCount,
430 VkQueueFamilyProperties* pQueueFamilyProperties)
431{
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700432 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700433
434 // Call down the call chain:
435 my_data->instance_dispatch_table->GetPhysicalDeviceQueueFamilyProperties(
436 physicalDevice,
437 pQueueFamilyPropertyCount,
438 pQueueFamilyProperties);
439
440 // Record the result of this query:
441 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700442 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Ian Elliott32311832016-02-04 08:17:18 -0700443 if (pPhysicalDevice &&
444 pQueueFamilyPropertyCount && !pQueueFamilyProperties) {
445 pPhysicalDevice->gotQueueFamilyPropertyCount = true;
446 pPhysicalDevice->numOfQueueFamilies =
447 *pQueueFamilyPropertyCount;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700448 }
Ian Elliott32311832016-02-04 08:17:18 -0700449 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700450}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700451
452#ifdef VK_USE_PLATFORM_ANDROID_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700453VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR(
454 VkInstance instance,
455 const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
456 const VkAllocationCallbacks* pAllocator,
457 VkSurfaceKHR* pSurface)
458{
459 VkResult result = VK_SUCCESS;
460 VkBool32 skipCall = VK_FALSE;
461 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700462 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700463 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700464
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700465 // Validate that the platform extension was enabled:
Cody Northropd08141b2016-02-01 09:52:07 -0700466 if (pInstance && !pInstance->androidSurfaceExtensionEnabled) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700467 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
468 pInstance,
469 "VkInstance",
470 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
471 "%s() called even though the %s extension was not enabled for this VkInstance.",
Cody Northropd08141b2016-02-01 09:52:07 -0700472 __FUNCTION__, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700473 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700474
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700475 if (!pCreateInfo) {
476 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
477 device,
478 "pCreateInfo");
479 } else {
480 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR) {
481 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
482 device,
483 "pCreateInfo",
484 "VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR");
485 }
486 if (pCreateInfo->pNext != NULL) {
487 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
488 device,
489 "pCreateInfo");
490 }
491 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700492
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700493 if (VK_FALSE == skipCall) {
494 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -0700495 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700496 result = my_data->instance_dispatch_table->CreateAndroidSurfaceKHR(
497 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliott32311832016-02-04 08:17:18 -0700498 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700499
Ian Elliott32311832016-02-04 08:17:18 -0700500 // Obtain this pointer again after locking:
501 pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700502 if ((result == VK_SUCCESS) && pInstance && pSurface) {
503 // Record the VkSurfaceKHR returned by the ICD:
504 my_data->surfaceMap[*pSurface].surface = *pSurface;
505 my_data->surfaceMap[*pSurface].pInstance = pInstance;
506 my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
507 (pAllocator != NULL);
508 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
509 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
510 // Point to the associated SwpInstance:
511 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
512 }
Ian Elliott32311832016-02-04 08:17:18 -0700513 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700514 return result;
515 }
Ian Elliott32311832016-02-04 08:17:18 -0700516 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700517 return VK_ERROR_VALIDATION_FAILED_EXT;
518}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700519#endif // VK_USE_PLATFORM_ANDROID_KHR
520
521#ifdef VK_USE_PLATFORM_MIR_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700522VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMirSurfaceKHR(
523 VkInstance instance,
524 const VkMirSurfaceCreateInfoKHR* pCreateInfo,
525 const VkAllocationCallbacks* pAllocator,
526 VkSurfaceKHR* pSurface)
527{
528 VkResult result = VK_SUCCESS;
529 VkBool32 skipCall = VK_FALSE;
530 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700531 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700532 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700533
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700534 // Validate that the platform extension was enabled:
535 if (pInstance && !pInstance->mirSurfaceExtensionEnabled) {
536 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
537 pInstance,
538 "VkInstance",
539 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
540 "%s() called even though the %s extension was not enabled for this VkInstance.",
541 __FUNCTION__, VK_KHR_MIR_SURFACE_EXTENSION_NAME);
542 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700543
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700544 if (!pCreateInfo) {
545 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
546 device,
547 "pCreateInfo");
548 } else {
549 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR) {
550 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
551 device,
552 "pCreateInfo",
553 "VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR");
554 }
555 if (pCreateInfo->pNext != NULL) {
556 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
557 device,
558 "pCreateInfo");
559 }
560 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700561
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700562 if (VK_FALSE == skipCall) {
563 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -0700564 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700565 result = my_data->instance_dispatch_table->CreateMirSurfaceKHR(
566 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliott32311832016-02-04 08:17:18 -0700567 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700568
Ian Elliott32311832016-02-04 08:17:18 -0700569 // Obtain this pointer again after locking:
570 pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700571 if ((result == VK_SUCCESS) && pInstance && pSurface) {
572 // Record the VkSurfaceKHR returned by the ICD:
573 my_data->surfaceMap[*pSurface].surface = *pSurface;
574 my_data->surfaceMap[*pSurface].pInstance = pInstance;
575 my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
576 (pAllocator != NULL);
577 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
578 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
579 // Point to the associated SwpInstance:
580 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
581 }
Ian Elliott32311832016-02-04 08:17:18 -0700582 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700583 return result;
584 }
Ian Elliott32311832016-02-04 08:17:18 -0700585 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700586 return VK_ERROR_VALIDATION_FAILED_EXT;
587}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700588
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700589VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceMirPresentationSupportKHR(
590 VkPhysicalDevice physicalDevice,
591 uint32_t queueFamilyIndex,
592 MirConnection* connection)
593{
594 VkBool32 result = VK_FALSE;
595 VkBool32 skipCall = VK_FALSE;
596 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700597 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700598 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700599
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700600 // Validate that the platform extension was enabled:
601 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
602 !pPhysicalDevice->pInstance->mirSurfaceExtensionEnabled) {
603 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
604 pPhysicalDevice->pInstance,
605 "VkInstance",
606 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
607 "%s() called even though the %s extension was not enabled for this VkInstance.",
608 __FUNCTION__, VK_KHR_MIR_SURFACE_EXTENSION_NAME);
609 }
610 if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
611 (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
612 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
613 pPhysicalDevice,
614 "VkPhysicalDevice",
615 queueFamilyIndex,
616 pPhysicalDevice->numOfQueueFamilies);
617 }
Ian Elliott32311832016-02-04 08:17:18 -0700618 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700619
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700620 if (VK_FALSE == skipCall) {
621 // Call down the call chain:
622 result = my_data->instance_dispatch_table->GetPhysicalDeviceMirPresentationSupportKHR(
623 physicalDevice, queueFamilyIndex, connection);
624 }
625 return result;
626}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700627#endif // VK_USE_PLATFORM_MIR_KHR
628
629#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700630VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR(
631 VkInstance instance,
632 const VkWaylandSurfaceCreateInfoKHR* pCreateInfo,
633 const VkAllocationCallbacks* pAllocator,
634 VkSurfaceKHR* pSurface)
635{
636 VkResult result = VK_SUCCESS;
637 VkBool32 skipCall = VK_FALSE;
638 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700639 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700640 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700641
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700642 // Validate that the platform extension was enabled:
643 if (pInstance && !pInstance->waylandSurfaceExtensionEnabled) {
644 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
645 pInstance,
646 "VkInstance",
647 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
648 "%s() called even though the %s extension was not enabled for this VkInstance.",
649 __FUNCTION__, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
650 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700651
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700652 if (!pCreateInfo) {
653 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
654 device,
655 "pCreateInfo");
656 } else {
657 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR) {
658 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
659 device,
660 "pCreateInfo",
661 "VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR");
662 }
663 if (pCreateInfo->pNext != NULL) {
664 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
665 device,
666 "pCreateInfo");
667 }
668 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700669
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700670 if (VK_FALSE == skipCall) {
671 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -0700672 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700673 result = my_data->instance_dispatch_table->CreateWaylandSurfaceKHR(
674 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliott32311832016-02-04 08:17:18 -0700675 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700676
Ian Elliott32311832016-02-04 08:17:18 -0700677 // Obtain this pointer again after locking:
678 pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700679 if ((result == VK_SUCCESS) && pInstance && pSurface) {
680 // Record the VkSurfaceKHR returned by the ICD:
681 my_data->surfaceMap[*pSurface].surface = *pSurface;
682 my_data->surfaceMap[*pSurface].pInstance = pInstance;
683 my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
684 (pAllocator != NULL);
685 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
686 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
687 // Point to the associated SwpInstance:
688 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
689 }
Ian Elliott32311832016-02-04 08:17:18 -0700690 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700691 return result;
692 }
Ian Elliott32311832016-02-04 08:17:18 -0700693 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700694 return VK_ERROR_VALIDATION_FAILED_EXT;
695}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700696
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700697VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWaylandPresentationSupportKHR(
698 VkPhysicalDevice physicalDevice,
699 uint32_t queueFamilyIndex,
700 struct wl_display* display)
701{
702 VkBool32 result = VK_FALSE;
703 VkBool32 skipCall = VK_FALSE;
704 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700705 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700706 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700707
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700708 // Validate that the platform extension was enabled:
709 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
710 !pPhysicalDevice->pInstance->waylandSurfaceExtensionEnabled) {
711 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
712 pPhysicalDevice->pInstance,
713 "VkInstance",
714 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
715 "%s() called even though the %s extension was not enabled for this VkInstance.",
716 __FUNCTION__, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
717 }
718 if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
719 (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
720 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
721 pPhysicalDevice,
722 "VkPhysicalDevice",
723 queueFamilyIndex,
724 pPhysicalDevice->numOfQueueFamilies);
725 }
Ian Elliott32311832016-02-04 08:17:18 -0700726 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700727
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700728 if (VK_FALSE == skipCall) {
729 // Call down the call chain:
730 result = my_data->instance_dispatch_table->GetPhysicalDeviceWaylandPresentationSupportKHR(
731 physicalDevice, queueFamilyIndex, display);
732 }
733 return result;
734}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700735#endif // VK_USE_PLATFORM_WAYLAND_KHR
736
737#ifdef VK_USE_PLATFORM_WIN32_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700738VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR(
739 VkInstance instance,
740 const VkWin32SurfaceCreateInfoKHR* pCreateInfo,
741 const VkAllocationCallbacks* pAllocator,
742 VkSurfaceKHR* pSurface)
743{
744 VkResult result = VK_SUCCESS;
745 VkBool32 skipCall = VK_FALSE;
746 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700747 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700748 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700749
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700750 // Validate that the platform extension was enabled:
751 if (pInstance && !pInstance->win32SurfaceExtensionEnabled) {
752 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
753 pInstance,
754 "VkInstance",
755 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
756 "%s() called even though the %s extension was not enabled for this VkInstance.",
757 __FUNCTION__, VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
758 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700759
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700760 if (!pCreateInfo) {
761 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
762 device,
763 "pCreateInfo");
764 } else {
765 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR) {
766 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
767 device,
768 "pCreateInfo",
769 "VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR");
770 }
771 if (pCreateInfo->pNext != NULL) {
772 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
773 device,
774 "pCreateInfo");
775 }
776 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700777
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700778 if (VK_FALSE == skipCall) {
779 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -0700780 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700781 result = my_data->instance_dispatch_table->CreateWin32SurfaceKHR(
782 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliott32311832016-02-04 08:17:18 -0700783 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700784
Ian Elliott32311832016-02-04 08:17:18 -0700785 // Obtain this pointer again after locking:
786 pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700787 if ((result == VK_SUCCESS) && pInstance && pSurface) {
788 // Record the VkSurfaceKHR returned by the ICD:
789 my_data->surfaceMap[*pSurface].surface = *pSurface;
790 my_data->surfaceMap[*pSurface].pInstance = pInstance;
791 my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
792 (pAllocator != NULL);
793 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
794 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
795 // Point to the associated SwpInstance:
796 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
797 }
Ian Elliott32311832016-02-04 08:17:18 -0700798 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700799 return result;
800 }
Ian Elliott32311832016-02-04 08:17:18 -0700801 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700802 return VK_ERROR_VALIDATION_FAILED_EXT;
803}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700804
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700805VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR(
806 VkPhysicalDevice physicalDevice,
807 uint32_t queueFamilyIndex)
808{
809 VkBool32 result = VK_FALSE;
810 VkBool32 skipCall = VK_FALSE;
811 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700812 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700813 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700814
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700815 // Validate that the platform extension was enabled:
816 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
817 !pPhysicalDevice->pInstance->win32SurfaceExtensionEnabled) {
818 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
819 pPhysicalDevice->pInstance,
820 "VkInstance",
821 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
822 "%s() called even though the %s extension was not enabled for this VkInstance.",
823 __FUNCTION__, VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
824 }
825 if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
826 (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
827 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
828 pPhysicalDevice,
829 "VkPhysicalDevice",
830 queueFamilyIndex,
831 pPhysicalDevice->numOfQueueFamilies);
832 }
Ian Elliott32311832016-02-04 08:17:18 -0700833 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700834
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700835 if (VK_FALSE == skipCall) {
836 // Call down the call chain:
837 result = my_data->instance_dispatch_table->GetPhysicalDeviceWin32PresentationSupportKHR(
838 physicalDevice, queueFamilyIndex);
839 }
840 return result;
841}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700842#endif // VK_USE_PLATFORM_WIN32_KHR
843
844#ifdef VK_USE_PLATFORM_XCB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700845VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(
846 VkInstance instance,
847 const VkXcbSurfaceCreateInfoKHR* pCreateInfo,
848 const VkAllocationCallbacks* pAllocator,
849 VkSurfaceKHR* pSurface)
850{
851 VkResult result = VK_SUCCESS;
852 VkBool32 skipCall = VK_FALSE;
853 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700854 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700855 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700856
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700857 // Validate that the platform extension was enabled:
858 if (pInstance && !pInstance->xcbSurfaceExtensionEnabled) {
859 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
860 pInstance,
861 "VkInstance",
862 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
863 "%s() called even though the %s extension was not enabled for this VkInstance.",
864 __FUNCTION__, VK_KHR_XCB_SURFACE_EXTENSION_NAME);
865 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700866
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700867 if (!pCreateInfo) {
868 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
869 device,
870 "pCreateInfo");
871 } else {
872 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR) {
873 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
874 device,
875 "pCreateInfo",
876 "VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR");
877 }
878 if (pCreateInfo->pNext != NULL) {
879 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
880 device,
881 "pCreateInfo");
882 }
883 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700884
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700885 if (VK_FALSE == skipCall) {
886 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -0700887 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700888 result = my_data->instance_dispatch_table->CreateXcbSurfaceKHR(
889 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliott32311832016-02-04 08:17:18 -0700890 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700891
Ian Elliott32311832016-02-04 08:17:18 -0700892 // Obtain this pointer again after locking:
893 pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700894 if ((result == VK_SUCCESS) && pInstance && pSurface) {
895 // Record the VkSurfaceKHR returned by the ICD:
896 my_data->surfaceMap[*pSurface].surface = *pSurface;
897 my_data->surfaceMap[*pSurface].pInstance = pInstance;
898 my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
899 (pAllocator != NULL);
900 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
901 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
902 // Point to the associated SwpInstance:
903 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
904 }
Ian Elliott32311832016-02-04 08:17:18 -0700905 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700906 return result;
907 }
Ian Elliott32311832016-02-04 08:17:18 -0700908 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700909 return VK_ERROR_VALIDATION_FAILED_EXT;
910}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700911
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700912VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXcbPresentationSupportKHR(
913 VkPhysicalDevice physicalDevice,
914 uint32_t queueFamilyIndex,
915 xcb_connection_t* connection,
916 xcb_visualid_t visual_id)
917{
918 VkBool32 result = VK_FALSE;
919 VkBool32 skipCall = VK_FALSE;
920 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700921 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700922 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700923
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700924 // Validate that the platform extension was enabled:
925 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
926 !pPhysicalDevice->pInstance->xcbSurfaceExtensionEnabled) {
927 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
928 pPhysicalDevice->pInstance,
929 "VkInstance",
930 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
931 "%s() called even though the %s extension was not enabled for this VkInstance.",
932 __FUNCTION__, VK_KHR_XCB_SURFACE_EXTENSION_NAME);
933 }
934 if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
935 (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
936 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
937 pPhysicalDevice,
938 "VkPhysicalDevice",
939 queueFamilyIndex,
940 pPhysicalDevice->numOfQueueFamilies);
941 }
Ian Elliott32311832016-02-04 08:17:18 -0700942 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700943
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700944 if (VK_FALSE == skipCall) {
945 // Call down the call chain:
946 result = my_data->instance_dispatch_table->GetPhysicalDeviceXcbPresentationSupportKHR(
947 physicalDevice, queueFamilyIndex, connection, visual_id);
948 }
949 return result;
950}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700951#endif // VK_USE_PLATFORM_XCB_KHR
952
953#ifdef VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700954VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(
955 VkInstance instance,
956 const VkXlibSurfaceCreateInfoKHR* pCreateInfo,
957 const VkAllocationCallbacks* pAllocator,
958 VkSurfaceKHR* pSurface)
959{
960 VkResult result = VK_SUCCESS;
961 VkBool32 skipCall = VK_FALSE;
962 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700963 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700964 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700965
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700966 // Validate that the platform extension was enabled:
967 if (pInstance && !pInstance->xlibSurfaceExtensionEnabled) {
968 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
969 pInstance,
970 "VkInstance",
971 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
972 "%s() called even though the %s extension was not enabled for this VkInstance.",
973 __FUNCTION__, VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
974 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700975
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700976 if (!pCreateInfo) {
977 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
978 device,
979 "pCreateInfo");
980 } else {
981 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR) {
982 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
983 device,
984 "pCreateInfo",
985 "VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR");
986 }
987 if (pCreateInfo->pNext != NULL) {
988 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
989 device,
990 "pCreateInfo");
991 }
992 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700993
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700994 if (VK_FALSE == skipCall) {
995 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -0700996 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700997 result = my_data->instance_dispatch_table->CreateXlibSurfaceKHR(
998 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliott32311832016-02-04 08:17:18 -0700999 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001000
Ian Elliott32311832016-02-04 08:17:18 -07001001 // Obtain this pointer again after locking:
1002 pInstance = &(my_data->instanceMap[instance]);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001003 if ((result == VK_SUCCESS) && pInstance && pSurface) {
1004 // Record the VkSurfaceKHR returned by the ICD:
1005 my_data->surfaceMap[*pSurface].surface = *pSurface;
1006 my_data->surfaceMap[*pSurface].pInstance = pInstance;
1007 my_data->surfaceMap[*pSurface].usedAllocatorToCreate =
1008 (pAllocator != NULL);
1009 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
1010 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
1011 // Point to the associated SwpInstance:
1012 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
1013 }
Ian Elliott32311832016-02-04 08:17:18 -07001014 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001015 return result;
1016 }
Ian Elliott32311832016-02-04 08:17:18 -07001017 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001018 return VK_ERROR_VALIDATION_FAILED_EXT;
1019}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001020
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001021VK_LAYER_EXPORT VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR(
1022 VkPhysicalDevice physicalDevice,
1023 uint32_t queueFamilyIndex,
1024 Display* dpy,
1025 VisualID visualID)
1026{
1027 VkBool32 result = VK_FALSE;
1028 VkBool32 skipCall = VK_FALSE;
1029 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001030 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001031 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001032
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001033 // Validate that the platform extension was enabled:
1034 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
1035 !pPhysicalDevice->pInstance->xlibSurfaceExtensionEnabled) {
1036 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1037 pPhysicalDevice->pInstance,
1038 "VkInstance",
1039 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1040 "%s() called even though the %s extension was not enabled for this VkInstance.",
1041 __FUNCTION__, VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
1042 }
1043 if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
1044 (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
1045 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1046 pPhysicalDevice,
1047 "VkPhysicalDevice",
1048 queueFamilyIndex,
1049 pPhysicalDevice->numOfQueueFamilies);
1050 }
Ian Elliott32311832016-02-04 08:17:18 -07001051 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001052
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001053 if (VK_FALSE == skipCall) {
1054 // Call down the call chain:
1055 result = my_data->instance_dispatch_table->GetPhysicalDeviceXlibPresentationSupportKHR(
1056 physicalDevice, queueFamilyIndex, dpy, visualID);
1057 }
1058 return result;
1059}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001060#endif // VK_USE_PLATFORM_XLIB_KHR
1061
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001062VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator)
1063{
1064 VkBool32 skipCall = VK_FALSE;
1065 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001066 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001067 SwpSurface *pSurface = &my_data->surfaceMap[surface];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001068
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001069 // Regardless of skipCall value, do some internal cleanup:
1070 if (pSurface) {
1071 // Delete the SwpSurface associated with this surface:
1072 if (pSurface->pInstance) {
1073 pSurface->pInstance->surfaces.erase(surface);
1074 }
1075 if (!pSurface->swapchains.empty()) {
1076 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance",
1077 SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
1078 "%s() called before all of its associated "
1079 "VkSwapchainKHRs were destroyed.",
1080 __FUNCTION__);
1081 // Empty and then delete all SwpSwapchain's
1082 for (auto it = pSurface->swapchains.begin() ;
1083 it != pSurface->swapchains.end() ; it++) {
1084 // Delete all SwpImage's
1085 it->second->images.clear();
1086 // In case the swapchain's device hasn't been destroyed yet
1087 // (which isn't likely, but is possible), delete its
1088 // association with this swapchain (i.e. so we can't point to
1089 // this swpchain from that device, later on):
1090 if (it->second->pDevice) {
1091 it->second->pDevice->swapchains.clear();
1092 }
1093 }
1094 pSurface->swapchains.clear();
1095 }
1096 if ((pAllocator != NULL) != pSurface->usedAllocatorToCreate) {
1097 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance",
1098 SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
1099 "%s() called with incompatible pAllocator from when "
1100 "the object was created.",
1101 __FUNCTION__);
1102 }
1103 my_data->surfaceMap.erase(surface);
1104 }
Ian Elliott32311832016-02-04 08:17:18 -07001105 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001106
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001107 if (VK_FALSE == skipCall) {
1108 // Call down the call chain:
1109 my_data->instance_dispatch_table->DestroySurfaceKHR(
1110 instance, surface, pAllocator);
1111 }
1112}
1113
1114VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices)
1115{
1116 VkResult result = VK_SUCCESS;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001117 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001118
1119 // Call down the call chain:
1120 result = my_data->instance_dispatch_table->EnumeratePhysicalDevices(
1121 instance, pPhysicalDeviceCount, pPhysicalDevices);
1122
1123 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001124 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Ian Elliott32311832016-02-04 08:17:18 -07001125 if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices &&
1126 (*pPhysicalDeviceCount > 0)) {
1127 // Record the VkPhysicalDevices returned by the ICD:
1128 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
1129 my_data->physicalDeviceMap[pPhysicalDevices[i]].physicalDevice =
1130 pPhysicalDevices[i];
1131 my_data->physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance;
1132 my_data->physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL;
1133 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotQueueFamilyPropertyCount = false;
1134 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotSurfaceCapabilities = false;
1135 my_data->physicalDeviceMap[pPhysicalDevices[i]].surfaceFormatCount = 0;
1136 my_data->physicalDeviceMap[pPhysicalDevices[i]].pSurfaceFormats = NULL;
1137 my_data->physicalDeviceMap[pPhysicalDevices[i]].presentModeCount = 0;
1138 my_data->physicalDeviceMap[pPhysicalDevices[i]].pPresentModes = NULL;
1139 // Point to the associated SwpInstance:
1140 if (pInstance) {
1141 pInstance->physicalDevices[pPhysicalDevices[i]] =
1142 &my_data->physicalDeviceMap[pPhysicalDevices[i]];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001143 }
1144 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001145 }
Ian Elliott32311832016-02-04 08:17:18 -07001146 loader_platform_thread_unlock_mutex(&globalLock);
Ian Elliotta3c69bc2016-02-04 15:34:59 -07001147 return result;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001148}
1149
1150VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice)
1151{
1152 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
1153
1154 assert(chain_info->u.pLayerInfo);
1155 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
1156 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
1157 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
1158 if (fpCreateDevice == NULL) {
1159 return VK_ERROR_INITIALIZATION_FAILED;
1160 }
1161
1162 // Advance the link info for the next element on the chain
1163 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
1164
1165 VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1166 if (result != VK_SUCCESS) {
1167 return result;
1168 }
1169
Ian Elliott32311832016-02-04 08:17:18 -07001170 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001171 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1172 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
1173
1174 // Setup device dispatch table
1175 my_device_data->device_dispatch_table = new VkLayerDispatchTable;
1176 layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
1177
1178 my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
1179 createDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice);
Ian Elliott32311832016-02-04 08:17:18 -07001180 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001181
1182 return result;
1183}
1184
1185VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator)
1186{
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001187 dispatch_key key = get_dispatch_key(device);
1188 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001189
1190 // Call down the call chain:
1191 my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
1192
1193 // Do some internal cleanup:
1194 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001195 SwpDevice *pDevice = &my_data->deviceMap[device];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001196 if (pDevice) {
1197 // Delete the SwpDevice associated with this device:
1198 if (pDevice->pPhysicalDevice) {
1199 pDevice->pPhysicalDevice->pDevice = NULL;
1200 }
1201 if (!pDevice->swapchains.empty()) {
1202 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1203 SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
1204 "%s() called before all of its associated "
1205 "VkSwapchainKHRs were destroyed.",
1206 __FUNCTION__);
1207 // Empty and then delete all SwpSwapchain's
1208 for (auto it = pDevice->swapchains.begin() ;
1209 it != pDevice->swapchains.end() ; it++) {
1210 // Delete all SwpImage's
1211 it->second->images.clear();
1212 // In case the swapchain's surface hasn't been destroyed yet
1213 // (which is likely) delete its association with this swapchain
1214 // (i.e. so we can't point to this swpchain from that surface,
1215 // later on):
1216 if (it->second->pSurface) {
1217 it->second->pSurface->swapchains.clear();
1218 }
1219 }
1220 pDevice->swapchains.clear();
1221 }
1222 my_data->deviceMap.erase(device);
1223 }
1224 delete my_data->device_dispatch_table;
1225 layer_data_map.erase(key);
Ian Elliott32311832016-02-04 08:17:18 -07001226 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001227}
1228
1229VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(
1230 VkPhysicalDevice physicalDevice,
1231 uint32_t queueFamilyIndex,
1232 VkSurfaceKHR surface,
1233 VkBool32* pSupported)
1234{
1235 VkResult result = VK_SUCCESS;
1236 VkBool32 skipCall = VK_FALSE;
1237 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001238 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001239 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
1240
1241 // Validate that the surface extension was enabled:
1242 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
1243 !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1244 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1245 pPhysicalDevice->pInstance,
1246 "VkInstance",
1247 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1248 "%s() called even though the %s extension was not enabled for this VkInstance.",
1249 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
1250 }
1251 if (!pPhysicalDevice->gotQueueFamilyPropertyCount) {
1252 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1253 pPhysicalDevice,
1254 "VkPhysicalDevice",
1255 SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES,
1256 "%s() called before calling the "
1257 "vkGetPhysicalDeviceQueueFamilyProperties "
1258 "function.",
1259 __FUNCTION__);
1260 } else if (pPhysicalDevice->gotQueueFamilyPropertyCount &&
1261 (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
1262 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1263 pPhysicalDevice,
1264 "VkPhysicalDevice",
1265 queueFamilyIndex,
1266 pPhysicalDevice->numOfQueueFamilies);
1267 }
1268 if (!pSupported) {
1269 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1270 physicalDevice,
1271 "pSupported");
1272 }
1273
1274 if (VK_FALSE == skipCall) {
1275 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -07001276 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001277 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(
1278 physicalDevice, queueFamilyIndex, surface,
1279 pSupported);
Ian Elliott32311832016-02-04 08:17:18 -07001280 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001281
Ian Elliott32311832016-02-04 08:17:18 -07001282 // Obtain this pointer again after locking:
1283 pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001284 if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
1285 // Record the result of this query:
1286 SwpInstance *pInstance = pPhysicalDevice->pInstance;
1287 SwpSurface *pSurface =
1288 (pInstance) ? pInstance->surfaces[surface] : NULL;
1289 if (pSurface) {
1290 pPhysicalDevice->supportedSurfaces[surface] = pSurface;
1291 if (!pSurface->numQueueFamilyIndexSupport) {
1292 if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
1293 pSurface->pQueueFamilyIndexSupport = (VkBool32 *)
1294 malloc(pPhysicalDevice->numOfQueueFamilies *
1295 sizeof(VkBool32));
1296 if (pSurface->pQueueFamilyIndexSupport != NULL) {
1297 pSurface->numQueueFamilyIndexSupport =
1298 pPhysicalDevice->numOfQueueFamilies;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001299 }
1300 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001301 }
1302 if (pSurface->numQueueFamilyIndexSupport) {
1303 pSurface->pQueueFamilyIndexSupport[queueFamilyIndex] =
1304 *pSupported;
1305 }
1306 }
1307 }
Ian Elliott32311832016-02-04 08:17:18 -07001308 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001309 return result;
1310 }
Ian Elliott32311832016-02-04 08:17:18 -07001311 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001312 return VK_ERROR_VALIDATION_FAILED_EXT;
1313}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001314
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001315VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
1316 VkPhysicalDevice physicalDevice,
1317 VkSurfaceKHR surface,
1318 VkSurfaceCapabilitiesKHR* pSurfaceCapabilities)
1319{
1320 VkResult result = VK_SUCCESS;
1321 VkBool32 skipCall = VK_FALSE;
1322 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001323 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001324 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001325
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001326 // Validate that the surface extension was enabled:
1327 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
1328 !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1329 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1330 pPhysicalDevice->pInstance,
1331 "VkInstance",
1332 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1333 "%s() called even though the %s extension was not enabled for this VkInstance.",
1334 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
1335 }
1336 if (!pSurfaceCapabilities) {
1337 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1338 physicalDevice,
1339 "pSurfaceCapabilities");
1340 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001341
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001342 if (VK_FALSE == skipCall) {
1343 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -07001344 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001345 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceCapabilitiesKHR(
1346 physicalDevice, surface, pSurfaceCapabilities);
Ian Elliott32311832016-02-04 08:17:18 -07001347 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001348
Ian Elliott32311832016-02-04 08:17:18 -07001349 // Obtain this pointer again after locking:
1350 pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001351 if ((result == VK_SUCCESS) && pPhysicalDevice) {
1352 // Record the result of this query:
1353 pPhysicalDevice->gotSurfaceCapabilities = true;
1354// FIXME: NEED TO COPY THIS DATA, BECAUSE pSurfaceCapabilities POINTS TO APP-ALLOCATED DATA
1355 pPhysicalDevice->surfaceCapabilities = *pSurfaceCapabilities;
1356 }
Ian Elliott32311832016-02-04 08:17:18 -07001357 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001358 return result;
1359 }
Ian Elliott32311832016-02-04 08:17:18 -07001360 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001361 return VK_ERROR_VALIDATION_FAILED_EXT;
1362}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001363
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001364VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR(
1365 VkPhysicalDevice physicalDevice,
1366 VkSurfaceKHR surface,
1367 uint32_t* pSurfaceFormatCount,
1368 VkSurfaceFormatKHR* pSurfaceFormats)
1369{
1370 VkResult result = VK_SUCCESS;
1371 VkBool32 skipCall = VK_FALSE;
1372 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001373 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001374 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001375
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001376 // Validate that the surface extension was enabled:
1377 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
1378 !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1379 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1380 pPhysicalDevice->pInstance,
1381 "VkInstance",
1382 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1383 "%s() called even though the %s extension was not enabled for this VkInstance.",
1384 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
1385 }
1386 if (!pSurfaceFormatCount) {
1387 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1388 physicalDevice,
1389 "pSurfaceFormatCount");
1390 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001391
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001392 if (VK_FALSE == skipCall) {
1393 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -07001394 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001395 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceFormatsKHR(
1396 physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats);
Ian Elliott32311832016-02-04 08:17:18 -07001397 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001398
Ian Elliott32311832016-02-04 08:17:18 -07001399 // Obtain this pointer again after locking:
1400 pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001401 if ((result == VK_SUCCESS) && pPhysicalDevice && !pSurfaceFormats &&
1402 pSurfaceFormatCount) {
1403 // Record the result of this preliminary query:
1404 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
1405 }
1406 else if ((result == VK_SUCCESS) && pPhysicalDevice && pSurfaceFormats &&
1407 pSurfaceFormatCount) {
1408 // Compare the preliminary value of *pSurfaceFormatCount with the
1409 // value this time:
1410 if (*pSurfaceFormatCount > pPhysicalDevice->surfaceFormatCount) {
1411 LOG_ERROR_INVALID_COUNT(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1412 physicalDevice,
1413 "pSurfaceFormatCount",
1414 "pSurfaceFormats",
1415 *pSurfaceFormatCount,
Ian Elliottf955d682015-12-30 12:00:54 -07001416 pPhysicalDevice->surfaceFormatCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001417 }
1418 else if (*pSurfaceFormatCount > 0) {
1419 // Record the result of this query:
1420 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
1421 pPhysicalDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)
1422 malloc(*pSurfaceFormatCount * sizeof(VkSurfaceFormatKHR));
1423 if (pPhysicalDevice->pSurfaceFormats) {
1424 for (uint32_t i = 0 ; i < *pSurfaceFormatCount ; i++) {
1425 pPhysicalDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
Ian Elliott9059b302015-12-30 13:14:36 -07001426 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001427 } else {
1428 pPhysicalDevice->surfaceFormatCount = 0;
1429 }
1430 }
1431 }
Ian Elliott32311832016-02-04 08:17:18 -07001432 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001433 return result;
1434 }
Ian Elliott32311832016-02-04 08:17:18 -07001435 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001436 return VK_ERROR_VALIDATION_FAILED_EXT;
1437}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001438
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001439VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR(
1440 VkPhysicalDevice physicalDevice,
1441 VkSurfaceKHR surface,
1442 uint32_t* pPresentModeCount,
1443 VkPresentModeKHR* pPresentModes)
1444{
1445 VkResult result = VK_SUCCESS;
1446 VkBool32 skipCall = VK_FALSE;
1447 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001448 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001449 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Ian Elliott07adb112016-01-05 12:51:03 -07001450
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001451 // Validate that the surface extension was enabled:
1452 if (pPhysicalDevice && pPhysicalDevice->pInstance &&
1453 !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1454 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
1455 pPhysicalDevice->pInstance,
1456 "VkInstance",
1457 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1458 "%s() called even though the %s extension was not enabled for this VkInstance.",
1459 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
1460 }
1461 if (!pPresentModeCount) {
1462 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1463 physicalDevice,
1464 "pPresentModeCount");
1465 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001466
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001467 if (VK_FALSE == skipCall) {
1468 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -07001469 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001470 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfacePresentModesKHR(
1471 physicalDevice, surface, pPresentModeCount, pPresentModes);
Ian Elliott32311832016-02-04 08:17:18 -07001472 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001473
Ian Elliott32311832016-02-04 08:17:18 -07001474 // Obtain this pointer again after locking:
1475 pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001476 if ((result == VK_SUCCESS) && pPhysicalDevice && !pPresentModes &&
1477 pPresentModeCount) {
1478 // Record the result of this preliminary query:
1479 pPhysicalDevice->presentModeCount = *pPresentModeCount;
1480 }
1481 else if ((result == VK_SUCCESS) && pPhysicalDevice && pPresentModes &&
1482 pPresentModeCount) {
1483 // Compare the preliminary value of *pPresentModeCount with the
1484 // value this time:
1485 if (*pPresentModeCount > pPhysicalDevice->presentModeCount) {
1486 LOG_ERROR_INVALID_COUNT(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1487 physicalDevice,
1488 "pPresentModeCount",
1489 "pPresentModes",
1490 *pPresentModeCount,
Ian Elliottf955d682015-12-30 12:00:54 -07001491 pPhysicalDevice->presentModeCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001492 }
1493 else if (*pPresentModeCount > 0) {
1494 // Record the result of this query:
1495 pPhysicalDevice->presentModeCount = *pPresentModeCount;
1496 pPhysicalDevice->pPresentModes = (VkPresentModeKHR *)
1497 malloc(*pPresentModeCount * sizeof(VkPresentModeKHR));
1498 if (pPhysicalDevice->pPresentModes) {
1499 for (uint32_t i = 0 ; i < *pPresentModeCount ; i++) {
1500 pPhysicalDevice->pPresentModes[i] = pPresentModes[i];
Ian Elliott9059b302015-12-30 13:14:36 -07001501 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001502 } else {
1503 pPhysicalDevice->presentModeCount = 0;
1504 }
1505 }
1506 }
Ian Elliott32311832016-02-04 08:17:18 -07001507 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001508 return result;
1509 }
Ian Elliott32311832016-02-04 08:17:18 -07001510 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001511 return VK_ERROR_VALIDATION_FAILED_EXT;
1512}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001513
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001514// This function does the up-front validation work for vkCreateSwapchainKHR(),
1515// and returns VK_TRUE if a logging callback indicates that the call down the
1516// chain should be skipped:
1517static VkBool32 validateCreateSwapchainKHR(
1518 VkDevice device,
1519 const VkSwapchainCreateInfoKHR* pCreateInfo,
1520 VkSwapchainKHR* pSwapchain)
1521{
1522// TODO: Validate cases of re-creating a swapchain (the current code
1523// assumes a new swapchain is being created).
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001524 VkBool32 skipCall = VK_FALSE;
1525 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1526 char fn[] = "vkCreateSwapchainKHR";
1527 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001528
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001529 // Validate that the swapchain extension was enabled:
1530 if (pDevice && !pDevice->swapchainExtensionEnabled) {
1531 return LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1532 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1533 "%s() called even though the %s extension was not enabled for this VkDevice.",
1534 fn, VK_KHR_SWAPCHAIN_EXTENSION_NAME );
1535 }
1536 if (!pCreateInfo) {
1537 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1538 device,
1539 "pCreateInfo");
1540 } else {
1541 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR) {
1542 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1543 device,
1544 "pCreateInfo",
1545 "VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR");
1546 }
1547 if (pCreateInfo->pNext != NULL) {
1548 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1549 device,
1550 "pCreateInfo");
1551 }
1552 }
1553 if (!pSwapchain) {
1554 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1555 device,
1556 "pSwapchain");
1557 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001558
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001559 // Keep around a useful pointer to pPhysicalDevice:
1560 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001561
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001562 // Validate pCreateInfo values with the results of
1563 // vkGetPhysicalDeviceSurfaceCapabilitiesKHR():
1564 if (!pPhysicalDevice || !pPhysicalDevice->gotSurfaceCapabilities) {
1565 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1566 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
1567 "%s() called before calling "
1568 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1569 fn);
1570 } else if (pCreateInfo) {
1571 // Validate pCreateInfo->surface to make sure that
1572 // vkGetPhysicalDeviceSurfaceSupportKHR() reported this as a supported
1573 // surface:
1574 SwpSurface *pSurface =
1575 ((pPhysicalDevice) ?
1576 pPhysicalDevice->supportedSurfaces[pCreateInfo->surface] : NULL);
1577 if (!pSurface) {
1578 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1579 SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE,
1580 "%s() called with pCreateInfo->surface that "
1581 "was not returned by "
1582 "vkGetPhysicalDeviceSurfaceSupportKHR() "
1583 "for the device.",
1584 fn);
1585 }
Ian Elliott4f147fc2016-01-20 08:52:08 -07001586
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001587 // Validate pCreateInfo->minImageCount against
1588 // VkSurfaceCapabilitiesKHR::{min|max}ImageCount:
1589 VkSurfaceCapabilitiesKHR *pCapabilities = &pPhysicalDevice->surfaceCapabilities;
1590 if ((pCreateInfo->minImageCount < pCapabilities->minImageCount) ||
1591 ((pCapabilities->maxImageCount > 0) &&
1592 (pCreateInfo->minImageCount > pCapabilities->maxImageCount))) {
1593 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1594 SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT,
1595 "%s() called with pCreateInfo->minImageCount "
1596 "= %d, which is outside the bounds returned "
1597 "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. "
1598 "minImageCount = %d, maxImageCount = %d).",
1599 fn,
1600 pCreateInfo->minImageCount,
1601 pCapabilities->minImageCount,
1602 pCapabilities->maxImageCount);
1603 }
1604 // Validate pCreateInfo->imageExtent against
1605 // VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
1606 if ((pCapabilities->currentExtent.width == -1) &&
1607 ((pCreateInfo->imageExtent.width < pCapabilities->minImageExtent.width) ||
1608 (pCreateInfo->imageExtent.width > pCapabilities->maxImageExtent.width) ||
1609 (pCreateInfo->imageExtent.height < pCapabilities->minImageExtent.height) ||
1610 (pCreateInfo->imageExtent.height > pCapabilities->maxImageExtent.height))) {
1611 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1612 SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS,
1613 "%s() called with pCreateInfo->imageExtent = "
1614 "(%d,%d), which is outside the bounds "
1615 "returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): "
1616 "currentExtent = (%d,%d), minImageExtent = "
1617 "(%d,%d), maxImageExtent = (%d,%d).",
1618 fn,
1619 pCreateInfo->imageExtent.width,
1620 pCreateInfo->imageExtent.height,
1621 pCapabilities->currentExtent.width,
1622 pCapabilities->currentExtent.height,
1623 pCapabilities->minImageExtent.width,
1624 pCapabilities->minImageExtent.height,
1625 pCapabilities->maxImageExtent.width,
1626 pCapabilities->maxImageExtent.height);
1627 }
1628 if ((pCapabilities->currentExtent.width != -1) &&
1629 ((pCreateInfo->imageExtent.width != pCapabilities->currentExtent.width) ||
1630 (pCreateInfo->imageExtent.height != pCapabilities->currentExtent.height))) {
1631 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1632 SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN,
1633 "%s() called with pCreateInfo->imageExtent = "
1634 "(%d,%d), which is not equal to the "
1635 "currentExtent = (%d,%d) returned by "
1636 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1637 fn,
1638 pCreateInfo->imageExtent.width,
1639 pCreateInfo->imageExtent.height,
1640 pCapabilities->currentExtent.width,
1641 pCapabilities->currentExtent.height);
1642 }
1643 // Validate pCreateInfo->preTransform has one bit set (1st two
1644 // lines of if-statement), which bit is also set in
1645 // VkSurfaceCapabilitiesKHR::supportedTransforms (3rd line of if-statement):
1646 if (!pCreateInfo->preTransform ||
1647 (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) ||
1648 !(pCreateInfo->preTransform & pCapabilities->supportedTransforms)) {
1649 // This is an error situation; one for which we'd like to give
1650 // the developer a helpful, multi-line error message. Build it
1651 // up a little at a time, and then log it:
1652 std::string errorString = "";
1653 char str[1024];
1654 // Here's the first part of the message:
1655 sprintf(str, "%s() called with a non-supported "
1656 "pCreateInfo->preTransform (i.e. %s). "
1657 "Supported values are:\n",
1658 fn,
1659 surfaceTransformStr(pCreateInfo->preTransform));
1660 errorString += str;
1661 for (int i = 0; i < 32; i++) {
1662 // Build up the rest of the message:
1663 if ((1 << i) & pCapabilities->supportedTransforms) {
1664 const char *newStr =
1665 surfaceTransformStr((VkSurfaceTransformFlagBitsKHR) (1 << i));
1666 sprintf(str, " %s\n", newStr);
1667 errorString += str;
1668 }
1669 }
1670 // Log the message that we've built up:
1671 skipCall |= debug_report_log_msg(my_data->report_data,
1672 VK_DEBUG_REPORT_ERROR_BIT_EXT,
1673 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1674 (uint64_t) device, __LINE__,
1675 SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM,
1676 LAYER_NAME,
1677 errorString.c_str());
1678 }
1679 // Validate pCreateInfo->compositeAlpha has one bit set (1st two
1680 // lines of if-statement), which bit is also set in
1681 // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha (3rd line of if-statement):
1682 if (!pCreateInfo->compositeAlpha ||
1683 (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) ||
1684 !((pCreateInfo->compositeAlpha) & pCapabilities->supportedCompositeAlpha)) {
1685 // This is an error situation; one for which we'd like to give
1686 // the developer a helpful, multi-line error message. Build it
1687 // up a little at a time, and then log it:
1688 std::string errorString = "";
1689 char str[1024];
1690 // Here's the first part of the message:
1691 sprintf(str, "%s() called with a non-supported "
1692 "pCreateInfo->compositeAlpha (i.e. %s). "
1693 "Supported values are:\n",
1694 fn,
1695 surfaceCompositeAlphaStr(pCreateInfo->compositeAlpha));
1696 errorString += str;
1697 for (int i = 0; i < 32; i++) {
1698 // Build up the rest of the message:
1699 if ((1 << i) & pCapabilities->supportedCompositeAlpha) {
1700 const char *newStr =
1701 surfaceCompositeAlphaStr((VkCompositeAlphaFlagBitsKHR) (1 << i));
1702 sprintf(str, " %s\n", newStr);
1703 errorString += str;
1704 }
1705 }
1706 // Log the message that we've built up:
1707 skipCall |= debug_report_log_msg(my_data->report_data,
1708 VK_DEBUG_REPORT_ERROR_BIT_EXT,
1709 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1710 (uint64_t) device, 0,
1711 SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA,
1712 LAYER_NAME,
1713 errorString.c_str());
1714 }
1715 // Validate pCreateInfo->imageArraySize against
1716 // VkSurfaceCapabilitiesKHR::maxImageArraySize:
1717 if ((pCreateInfo->imageArrayLayers < 1) ||
1718 (pCreateInfo->imageArrayLayers > pCapabilities->maxImageArrayLayers)) {
1719 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1720 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_SIZE,
1721 "%s() called with a non-supported "
1722 "pCreateInfo->imageArraySize (i.e. %d). "
1723 "Minimum value is 1, maximum value is %d.",
1724 fn,
1725 pCreateInfo->imageArrayLayers,
1726 pCapabilities->maxImageArrayLayers);
1727 }
1728 // Validate pCreateInfo->imageUsage against
1729 // VkSurfaceCapabilitiesKHR::supportedUsageFlags:
1730 if (pCreateInfo->imageUsage !=
1731 (pCreateInfo->imageUsage & pCapabilities->supportedUsageFlags)) {
1732 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1733 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS,
1734 "%s() called with a non-supported "
1735 "pCreateInfo->imageUsage (i.e. 0x%08x)."
1736 " Supported flag bits are 0x%08x.",
1737 fn,
1738 pCreateInfo->imageUsage,
1739 pCapabilities->supportedUsageFlags);
1740 }
1741 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001742
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001743 // Validate pCreateInfo values with the results of
1744 // vkGetPhysicalDeviceSurfaceFormatsKHR():
1745 if (!pPhysicalDevice || !pPhysicalDevice->surfaceFormatCount) {
1746 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1747 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
1748 "%s() called before calling "
1749 "vkGetPhysicalDeviceSurfaceFormatsKHR().",
1750 fn);
1751 } else if (pCreateInfo) {
1752 // Validate pCreateInfo->imageFormat against
1753 // VkSurfaceFormatKHR::format:
1754 bool foundFormat = false;
1755 bool foundColorSpace = false;
1756 bool foundMatch = false;
1757 for (uint32_t i = 0 ; i < pPhysicalDevice->surfaceFormatCount ; i++) {
1758 if (pCreateInfo->imageFormat == pPhysicalDevice->pSurfaceFormats[i].format) {
1759 // Validate pCreateInfo->imageColorSpace against
1760 // VkSurfaceFormatKHR::colorSpace:
1761 foundFormat = true;
1762 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1763 foundMatch = true;
1764 break;
1765 }
1766 } else {
1767 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1768 foundColorSpace = true;
1769 }
1770 }
1771 }
1772 if (!foundMatch) {
1773 if (!foundFormat) {
1774 if (!foundColorSpace) {
1775 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device,
1776 "VkDevice",
1777 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP,
1778 "%s() called with neither a "
1779 "supported pCreateInfo->imageFormat "
1780 "(i.e. %d) nor a supported "
1781 "pCreateInfo->imageColorSpace "
1782 "(i.e. %d).",
1783 fn,
1784 pCreateInfo->imageFormat,
1785 pCreateInfo->imageColorSpace);
1786 } else {
1787 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device,
1788 "VkDevice",
1789 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT,
1790 "%s() called with a non-supported "
1791 "pCreateInfo->imageFormat (i.e. %d).",
1792 fn, pCreateInfo->imageFormat);
1793 }
1794 } else if (!foundColorSpace) {
1795 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1796 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE,
1797 "%s() called with a non-supported "
1798 "pCreateInfo->imageColorSpace (i.e. %d).",
1799 fn, pCreateInfo->imageColorSpace);
1800 }
1801 }
1802 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001803
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001804 // Validate pCreateInfo values with the results of
1805 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1806 if (!pPhysicalDevice || !pPhysicalDevice->presentModeCount) {
1807 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1808 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
1809 "%s() called before calling "
1810 "vkGetPhysicalDeviceSurfacePresentModesKHR().",
1811 fn);
1812 } else if (pCreateInfo) {
1813 // Validate pCreateInfo->presentMode against
1814 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1815 bool foundMatch = false;
1816 for (uint32_t i = 0 ; i < pPhysicalDevice->presentModeCount ; i++) {
1817 if (pPhysicalDevice->pPresentModes[i] == pCreateInfo->presentMode) {
1818 foundMatch = true;
1819 break;
1820 }
1821 }
1822 if (!foundMatch) {
1823 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1824 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE,
1825 "%s() called with a non-supported "
1826 "pCreateInfo->presentMode (i.e. %s).",
1827 fn,
1828 presentModeStr(pCreateInfo->presentMode));
1829 }
1830 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001831
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001832 // Validate pCreateInfo->imageSharingMode and related values:
1833 if (pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT) {
1834 if ((pCreateInfo->queueFamilyIndexCount <= 1) ||
1835 !pCreateInfo->pQueueFamilyIndices) {
1836 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1837 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_VALUES,
1838 "%s() called with a supported "
1839 "pCreateInfo->sharingMode of (i.e. %s),"
1840 "but with a bad value(s) for "
1841 "pCreateInfo->queueFamilyIndexCount or "
1842 "pCreateInfo->pQueueFamilyIndices).",
1843 fn,
1844 sharingModeStr(pCreateInfo->imageSharingMode));
1845 }
1846 } else if (pCreateInfo->imageSharingMode != VK_SHARING_MODE_EXCLUSIVE) {
1847 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1848 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_MODE,
1849 "%s() called with a non-supported "
1850 "pCreateInfo->imageSharingMode (i.e. %s).",
1851 fn,
1852 sharingModeStr(pCreateInfo->imageSharingMode));
1853 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001854
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001855 // Validate pCreateInfo->clipped:
1856 if (pCreateInfo &&
1857 (pCreateInfo->clipped != VK_FALSE) &&
1858 (pCreateInfo->clipped != VK_TRUE)) {
1859 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1860 device, "VkDevice",
1861 SWAPCHAIN_BAD_BOOL,
1862 "%s() called with a VkBool32 value that is "
1863 "neither VK_TRUE nor VK_FALSE, but has the "
1864 "numeric value of %d.",
1865 fn,
1866 pCreateInfo->clipped);
1867 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001868
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001869 // Validate pCreateInfo->oldSwapchain:
1870 if (pCreateInfo && pCreateInfo->oldSwapchain) {
1871 SwpSwapchain *pOldSwapchain = &my_data->swapchainMap[pCreateInfo->oldSwapchain];
1872 if (pOldSwapchain) {
1873 if (device != pOldSwapchain->pDevice->device) {
1874 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1875 device, "VkDevice",
1876 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
1877 "%s() called with a different VkDevice "
1878 "than the VkSwapchainKHR was created with.",
1879 __FUNCTION__);
1880 }
1881 if (pCreateInfo->surface != pOldSwapchain->pSurface->surface) {
1882 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1883 device, "VkDevice",
1884 SWAPCHAIN_CREATE_SWAP_DIFF_SURFACE,
1885 "%s() called with pCreateInfo->oldSwapchain "
1886 "that has a different VkSurfaceKHR than "
1887 "pCreateInfo->surface.",
1888 fn);
1889 }
1890 } else {
1891 // TBD: Leave this in (not sure object_track will check this)?
1892 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
1893 pCreateInfo->oldSwapchain,
1894 "VkSwapchainKHR");
1895 }
1896 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001897
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001898 return skipCall;
1899}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001900
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001901VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(
1902 VkDevice device,
1903 const VkSwapchainCreateInfoKHR* pCreateInfo,
1904 const VkAllocationCallbacks* pAllocator,
1905 VkSwapchainKHR* pSwapchain)
1906{
1907 VkResult result = VK_SUCCESS;
1908 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001909 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001910 VkBool32 skipCall = validateCreateSwapchainKHR(device, pCreateInfo,
1911 pSwapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001912
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001913 if (VK_FALSE == skipCall) {
1914 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -07001915 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001916 result = my_data->device_dispatch_table->CreateSwapchainKHR(
1917 device, pCreateInfo, pAllocator, pSwapchain);
Ian Elliott32311832016-02-04 08:17:18 -07001918 loader_platform_thread_lock_mutex(&globalLock);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001919
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001920 if (result == VK_SUCCESS) {
1921 // Remember the swapchain's handle, and link it to the device:
1922 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001923
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001924 my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
1925 if (pDevice) {
1926 pDevice->swapchains[*pSwapchain] =
1927 &my_data->swapchainMap[*pSwapchain];
1928 }
1929 my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
1930 my_data->swapchainMap[*pSwapchain].imageCount = 0;
1931 my_data->swapchainMap[*pSwapchain].usedAllocatorToCreate =
1932 (pAllocator != NULL);
1933 // Store a pointer to the surface
1934 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
1935 SwpInstance *pInstance =
1936 (pPhysicalDevice) ? pPhysicalDevice->pInstance : NULL;
1937 layer_data *my_instance_data =
1938 ((pInstance) ?
1939 get_my_data_ptr(get_dispatch_key(pInstance->instance), layer_data_map) :
1940 NULL);
1941 SwpSurface *pSurface =
1942 ((my_data && pCreateInfo) ?
1943 &my_instance_data->surfaceMap[pCreateInfo->surface] : NULL);
1944 my_data->swapchainMap[*pSwapchain].pSurface = pSurface;
1945 if (pSurface) {
1946 pSurface->swapchains[*pSwapchain] =
1947 &my_data->swapchainMap[*pSwapchain];
1948 }
1949 }
Ian Elliott32311832016-02-04 08:17:18 -07001950 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001951 return result;
1952 }
Ian Elliott32311832016-02-04 08:17:18 -07001953 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001954 return VK_ERROR_VALIDATION_FAILED_EXT;
1955}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001956
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001957VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR(
1958 VkDevice device,
1959 VkSwapchainKHR swapchain,
1960 const VkAllocationCallbacks* pAllocator)
1961{
1962// TODOs:
1963//
1964// - Implement a check for validity language that reads: All uses of
1965// presentable images acquired from pname:swapchain and owned by the
1966// application must: have completed execution
1967 VkBool32 skipCall = VK_FALSE;
1968 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001969 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001970 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott8b9e2562016-01-05 13:00:50 -07001971
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001972 // Validate that the swapchain extension was enabled:
1973 if (pDevice && !pDevice->swapchainExtensionEnabled) {
1974 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1975 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1976 "%s() called even though the %s extension was not enabled for this VkDevice.",
1977 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
1978 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001979
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001980 // Regardless of skipCall value, do some internal cleanup:
1981 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
1982 if (pSwapchain) {
1983 // Delete the SwpSwapchain associated with this swapchain:
1984 if (pSwapchain->pDevice) {
1985 pSwapchain->pDevice->swapchains.erase(swapchain);
1986 if (device != pSwapchain->pDevice->device) {
1987 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1988 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
1989 "%s() called with a different VkDevice than the "
1990 "VkSwapchainKHR was created with.",
1991 __FUNCTION__);
1992 }
1993 }
1994 if (pSwapchain->pSurface) {
1995 pSwapchain->pSurface->swapchains.erase(swapchain);
1996 }
1997 if (pSwapchain->imageCount) {
1998 pSwapchain->images.clear();
1999 }
2000 if ((pAllocator != NULL) != pSwapchain->usedAllocatorToCreate) {
2001 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance",
2002 SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
2003 "%s() called with incompatible pAllocator from when "
2004 "the object was created.",
2005 __FUNCTION__);
2006 }
2007 my_data->swapchainMap.erase(swapchain);
2008 }
Ian Elliott32311832016-02-04 08:17:18 -07002009 loader_platform_thread_unlock_mutex(&globalLock);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002010
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002011 if (VK_FALSE == skipCall) {
2012 // Call down the call chain:
2013 my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator);
2014 }
2015}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002016
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002017VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR(
2018 VkDevice device,
2019 VkSwapchainKHR swapchain,
2020 uint32_t* pSwapchainImageCount,
2021 VkImage* pSwapchainImages)
2022{
2023 VkResult result = VK_SUCCESS;
2024 VkBool32 skipCall = VK_FALSE;
2025 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07002026 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002027 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott8b9e2562016-01-05 13:00:50 -07002028
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002029 // Validate that the swapchain extension was enabled:
2030 if (pDevice && !pDevice->swapchainExtensionEnabled) {
2031 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
2032 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2033 "%s() called even though the %s extension was not enabled for this VkDevice.",
2034 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
2035 }
2036 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
2037 if (!pSwapchainImageCount) {
2038 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2039 device,
2040 "pSwapchainImageCount");
2041 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002042
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002043 if (VK_FALSE == skipCall) {
2044 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -07002045 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002046 result = my_data->device_dispatch_table->GetSwapchainImagesKHR(
2047 device, swapchain, pSwapchainImageCount, pSwapchainImages);
Ian Elliott32311832016-02-04 08:17:18 -07002048 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002049
Ian Elliott32311832016-02-04 08:17:18 -07002050 // Obtain this pointer again after locking:
2051 pSwapchain = &my_data->swapchainMap[swapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002052 if ((result == VK_SUCCESS) && pSwapchain && !pSwapchainImages &&
2053 pSwapchainImageCount) {
2054 // Record the result of this preliminary query:
2055 pSwapchain->imageCount = *pSwapchainImageCount;
2056 }
2057 else if ((result == VK_SUCCESS) && pSwapchain && pSwapchainImages &&
2058 pSwapchainImageCount) {
2059 // Compare the preliminary value of *pSwapchainImageCount with the
2060 // value this time:
2061 if (*pSwapchainImageCount > pSwapchain->imageCount) {
2062 LOG_ERROR_INVALID_COUNT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2063 device,
2064 "pSwapchainImageCount",
Ian Elliottf955d682015-12-30 12:00:54 -07002065 "pSwapchainImages",
Ian Elliottdcf8eca2016-01-05 14:28:32 -07002066 *pSwapchainImageCount,
Ian Elliottf955d682015-12-30 12:00:54 -07002067 pSwapchain->imageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002068 }
2069 else if (*pSwapchainImageCount > 0) {
2070 // Record the images and their state:
2071 pSwapchain->imageCount = *pSwapchainImageCount;
2072 for (uint32_t i = 0 ; i < *pSwapchainImageCount ; i++) {
2073 pSwapchain->images[i].image = pSwapchainImages[i];
2074 pSwapchain->images[i].pSwapchain = pSwapchain;
2075 pSwapchain->images[i].ownedByApp = false;
2076 }
2077 }
2078 }
Ian Elliott32311832016-02-04 08:17:18 -07002079 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002080 return result;
2081 }
Ian Elliott32311832016-02-04 08:17:18 -07002082 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002083 return VK_ERROR_VALIDATION_FAILED_EXT;
2084}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002085
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002086VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR(
2087 VkDevice device,
2088 VkSwapchainKHR swapchain,
2089 uint64_t timeout,
2090 VkSemaphore semaphore,
2091 VkFence fence,
2092 uint32_t* pImageIndex)
2093{
2094// TODOs:
2095//
2096// - Address the timeout. Possibilities include looking at the state of the
2097// swapchain's images, depending on the timeout value.
2098// - Implement a check for validity language that reads: If pname:semaphore is
2099// not sname:VK_NULL_HANDLE it must: be unsignalled
2100// - Implement a check for validity language that reads: If pname:fence is not
2101// sname:VK_NULL_HANDLE it must: be unsignalled and mustnot: be associated
2102// with any other queue command that has not yet completed execution on that
2103// queue
2104// - Record/update the state of the swapchain, in case an error occurs
2105// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
2106 VkResult result = VK_SUCCESS;
2107 VkBool32 skipCall = VK_FALSE;
2108 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07002109 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002110 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott8b9e2562016-01-05 13:00:50 -07002111
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002112 // Validate that the swapchain extension was enabled:
2113 if (pDevice && !pDevice->swapchainExtensionEnabled) {
2114 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
2115 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2116 "%s() called even though the %s extension was not enabled for this VkDevice.",
2117 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
2118 }
2119 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
2120 if (pSwapchain) {
2121 // Look to see if the application is trying to own too many images at
2122 // the same time (i.e. not leave any to display):
2123 uint32_t imagesOwnedByApp = 0;
2124 for (uint32_t i = 0 ; i < pSwapchain->imageCount ; i++) {
2125 if (pSwapchain->images[i].ownedByApp) {
2126 imagesOwnedByApp++;
2127 }
2128 }
2129 if (imagesOwnedByApp >= (pSwapchain->imageCount - 1)) {
2130 skipCall |= LOG_PERF_WARNING(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
2131 swapchain,
2132 "VkSwapchainKHR",
2133 SWAPCHAIN_APP_OWNS_TOO_MANY_IMAGES,
2134 "%s() called when the application "
2135 "already owns all presentable images "
2136 "in this swapchain except for the "
2137 "image currently being displayed. "
2138 "This call to %s() cannot succeed "
2139 "unless another thread calls the "
2140 "vkQueuePresentKHR() function in "
2141 "order to release ownership of one of "
2142 "the presentable images of this "
2143 "swapchain.",
2144 __FUNCTION__, __FUNCTION__);
2145 }
2146 }
2147 if (!pImageIndex) {
2148 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2149 device,
2150 "pImageIndex");
2151 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002152
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002153 if (VK_FALSE == skipCall) {
2154 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -07002155 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002156 result = my_data->device_dispatch_table->AcquireNextImageKHR(
2157 device, swapchain, timeout, semaphore, fence, pImageIndex);
Ian Elliott32311832016-02-04 08:17:18 -07002158 loader_platform_thread_lock_mutex(&globalLock);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002159
Ian Elliott32311832016-02-04 08:17:18 -07002160 // Obtain this pointer again after locking:
2161 pSwapchain = &my_data->swapchainMap[swapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002162 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) &&
2163 pSwapchain) {
2164 // Change the state of the image (now owned by the application):
2165 pSwapchain->images[*pImageIndex].ownedByApp = true;
2166 }
Ian Elliott32311832016-02-04 08:17:18 -07002167 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002168 return result;
2169 }
Ian Elliott32311832016-02-04 08:17:18 -07002170 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002171 return VK_ERROR_VALIDATION_FAILED_EXT;
2172}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002173
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002174VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(
2175 VkQueue queue,
2176 const VkPresentInfoKHR* pPresentInfo)
2177{
2178// TODOs:
2179//
2180// - Implement a check for validity language that reads: Any given element of
2181// sname:VkSemaphore in pname:pWaitSemaphores must: refer to a prior signal
2182// of that sname:VkSemaphore that won't be consumed by any other wait on that
2183// semaphore
2184// - Record/update the state of the swapchain, in case an error occurs
2185// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
2186 VkResult result = VK_SUCCESS;
2187 VkBool32 skipCall = VK_FALSE;
2188 layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002189
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002190 if (!pPresentInfo) {
2191 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2192 device,
2193 "pPresentInfo");
2194 } else {
2195 if (pPresentInfo->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR) {
2196 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2197 device,
2198 "pPresentInfo",
2199 "VK_STRUCTURE_TYPE_PRESENT_INFO_KHR");
2200 }
2201 if (pPresentInfo->pNext != NULL) {
2202 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2203 device,
2204 "pPresentInfo");
2205 }
2206 if (!pPresentInfo->swapchainCount) {
2207 skipCall |= LOG_ERROR_ZERO_VALUE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2208 device,
2209 "pPresentInfo->swapchainCount");
2210 }
2211 if (!pPresentInfo->pSwapchains) {
2212 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2213 device,
2214 "pPresentInfo->pSwapchains");
2215 }
2216 if (!pPresentInfo->pImageIndices) {
2217 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2218 device,
2219 "pPresentInfo->pImageIndices");
2220 }
2221 // Note: pPresentInfo->pResults is allowed to be NULL
2222 }
Ian Elliott046ed2c2015-12-30 17:07:17 -07002223
Ian Elliott32311832016-02-04 08:17:18 -07002224 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002225 for (uint32_t i = 0;
2226 pPresentInfo && (i < pPresentInfo->swapchainCount);
2227 i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002228 uint32_t index = pPresentInfo->pImageIndices[i];
2229 SwpSwapchain *pSwapchain =
2230 &my_data->swapchainMap[pPresentInfo->pSwapchains[i]];
2231 if (pSwapchain) {
2232 if (!pSwapchain->pDevice->swapchainExtensionEnabled) {
2233 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2234 pSwapchain->pDevice, "VkDevice",
2235 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2236 "%s() called even though the %s extension was not enabled for this VkDevice.",
2237 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
2238 }
2239 if (index >= pSwapchain->imageCount) {
2240 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
2241 pPresentInfo->pSwapchains[i],
2242 "VkSwapchainKHR",
2243 SWAPCHAIN_INDEX_TOO_LARGE,
2244 "%s() called for an index that is too "
2245 "large (i.e. %d). There are only %d "
2246 "images in this VkSwapchainKHR.\n",
2247 __FUNCTION__, index,
2248 pSwapchain->imageCount);
2249 } else {
2250 if (!pSwapchain->images[index].ownedByApp) {
2251 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
2252 pPresentInfo->pSwapchains[i],
2253 "VkSwapchainKHR",
2254 SWAPCHAIN_INDEX_NOT_IN_USE,
2255 "%s() returned an index (i.e. %d) "
2256 "for an image that is not owned by "
2257 "the application.",
2258 __FUNCTION__, index);
2259 }
2260 }
2261 SwpQueue *pQueue = &my_data->queueMap[queue];
2262 SwpSurface *pSurface = pSwapchain->pSurface;
2263 if (pQueue && pSurface && pSurface->numQueueFamilyIndexSupport) {
2264 uint32_t queueFamilyIndex = pQueue->queueFamilyIndex;
2265 // Note: the 1st test is to ensure queueFamilyIndex is in range,
2266 // and the 2nd test is the validation check:
2267 if ((pSurface->numQueueFamilyIndexSupport > queueFamilyIndex) &&
2268 (!pSurface->pQueueFamilyIndexSupport[queueFamilyIndex])) {
2269 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
2270 pPresentInfo->pSwapchains[i],
2271 "VkSwapchainKHR",
2272 SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE,
2273 "%s() called with a swapchain whose "
2274 "surface is not supported for "
2275 "presention on this device with the "
2276 "queueFamilyIndex (i.e. %d) of the "
2277 "given queue.",
2278 __FUNCTION__, queueFamilyIndex);
2279 }
2280 }
2281 }
2282 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002283
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002284 if (VK_FALSE == skipCall) {
2285 // Call down the call chain:
Ian Elliott32311832016-02-04 08:17:18 -07002286 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002287 result = my_data->device_dispatch_table->QueuePresentKHR(queue,
2288 pPresentInfo);
Ian Elliott32311832016-02-04 08:17:18 -07002289 loader_platform_thread_lock_mutex(&globalLock);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002290
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002291 if (pPresentInfo &&
2292 ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR))) {
2293 for (uint32_t i = 0; i < pPresentInfo->swapchainCount ; i++) {
2294 int index = pPresentInfo->pImageIndices[i];
2295 SwpSwapchain *pSwapchain =
2296 &my_data->swapchainMap[pPresentInfo->pSwapchains[i]];
2297 if (pSwapchain) {
2298 // Change the state of the image (no longer owned by the
2299 // application):
2300 pSwapchain->images[index].ownedByApp = false;
2301 }
2302 }
2303 }
Ian Elliott32311832016-02-04 08:17:18 -07002304 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002305 return result;
2306 }
Ian Elliott32311832016-02-04 08:17:18 -07002307 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002308 return VK_ERROR_VALIDATION_FAILED_EXT;
2309}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002310
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002311VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue(
2312 VkDevice device,
2313 uint32_t queueFamilyIndex,
2314 uint32_t queueIndex,
2315 VkQueue* pQueue)
2316{
2317 VkBool32 skipCall = VK_FALSE;
2318 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliottc4db6952016-01-21 14:29:45 -07002319
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002320 if (VK_FALSE == skipCall) {
2321 // Call down the call chain:
2322 my_data->device_dispatch_table->GetDeviceQueue(
2323 device, queueFamilyIndex, queueIndex, pQueue);
Ian Elliottc4db6952016-01-21 14:29:45 -07002324
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002325 // Remember the queue's handle, and link it to the device:
Ian Elliott32311832016-02-04 08:17:18 -07002326 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002327 SwpDevice *pDevice = &my_data->deviceMap[device];
2328 my_data->queueMap[&pQueue].queue = *pQueue;
2329 if (pDevice) {
2330 pDevice->queues[*pQueue] = &my_data->queueMap[*pQueue];
2331 }
2332 my_data->queueMap[&pQueue].pDevice = pDevice;
2333 my_data->queueMap[&pQueue].queueFamilyIndex = queueFamilyIndex;
Ian Elliott32311832016-02-04 08:17:18 -07002334 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002335 }
2336}
Ian Elliottc4db6952016-01-21 14:29:45 -07002337
2338
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002339VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(
2340 VkInstance instance,
2341 const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
2342 const VkAllocationCallbacks* pAllocator,
2343 VkDebugReportCallbackEXT* pMsgCallback)
2344{
2345 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2346 VkResult result = my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
2347 if (VK_SUCCESS == result) {
Ian Elliott32311832016-02-04 08:17:18 -07002348 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002349 result = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback);
Ian Elliott32311832016-02-04 08:17:18 -07002350 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002351 }
2352 return result;
2353}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002354
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002355VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, const VkAllocationCallbacks *pAllocator)
2356{
2357 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2358 my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Ian Elliott32311832016-02-04 08:17:18 -07002359 loader_platform_thread_lock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002360 layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
Ian Elliott32311832016-02-04 08:17:18 -07002361 loader_platform_thread_unlock_mutex(&globalLock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002362}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002363
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002364VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(
2365 VkInstance instance,
2366 VkDebugReportFlagsEXT flags,
2367 VkDebugReportObjectTypeEXT objType,
2368 uint64_t object,
2369 size_t location,
2370 int32_t msgCode,
2371 const char* pLayerPrefix,
2372 const char* pMsg)
2373{
2374 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2375 my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
2376}
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07002377
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002378VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)
2379{
2380 if (!strcmp("vkGetDeviceProcAddr", funcName))
2381 return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
2382 if (!strcmp(funcName, "vkDestroyDevice"))
2383 return (PFN_vkVoidFunction) vkDestroyDevice;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002384
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002385 if (device == VK_NULL_HANDLE) {
2386 return NULL;
2387 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002388
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002389 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06002390
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002391 my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2392 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
2393 if (my_data->deviceMap.size() != 0 &&
2394 my_data->deviceMap[device].swapchainExtensionEnabled)
2395 {
2396 if (!strcmp("vkCreateSwapchainKHR", funcName))
2397 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateSwapchainKHR);
2398 if (!strcmp("vkDestroySwapchainKHR", funcName))
2399 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySwapchainKHR);
2400 if (!strcmp("vkGetSwapchainImagesKHR", funcName))
2401 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSwapchainImagesKHR);
2402 if (!strcmp("vkAcquireNextImageKHR", funcName))
2403 return reinterpret_cast<PFN_vkVoidFunction>(vkAcquireNextImageKHR);
2404 if (!strcmp("vkQueuePresentKHR", funcName))
2405 return reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR);
2406 }
2407 if (!strcmp("vkGetDeviceQueue", funcName))
2408 return reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceQueue);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002409
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002410 if (pDisp->GetDeviceProcAddr == NULL)
2411 return NULL;
2412 return pDisp->GetDeviceProcAddr(device, funcName);
2413}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002414
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002415VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
2416{
2417 if (!strcmp("vkGetInstanceProcAddr", funcName))
2418 return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
2419 if (!strcmp(funcName, "vkCreateInstance"))
2420 return (PFN_vkVoidFunction) vkCreateInstance;
2421 if (!strcmp(funcName, "vkDestroyInstance"))
2422 return (PFN_vkVoidFunction) vkDestroyInstance;
2423 if (!strcmp(funcName, "vkCreateDevice"))
2424 return (PFN_vkVoidFunction) vkCreateDevice;
2425 if (!strcmp(funcName, "vkEnumeratePhysicalDevices"))
2426 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
2427 if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
2428 return (PFN_vkVoidFunction) vkEnumerateInstanceLayerProperties;
Courtney Goeltzenleuchterbeb42f82016-02-12 13:46:04 -07002429 if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties"))
2430 return (PFN_vkVoidFunction)vkEnumerateDeviceLayerProperties;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002431 if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
2432 return (PFN_vkVoidFunction) vkEnumerateInstanceExtensionProperties;
Courtney Goeltzenleuchterbeb42f82016-02-12 13:46:04 -07002433 if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties"))
2434 return (PFN_vkVoidFunction)vkEnumerateDeviceExtensionProperties;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002435 if (!strcmp(funcName, "vkGetPhysicalDeviceQueueFamilyProperties"))
2436 return (PFN_vkVoidFunction) vkGetPhysicalDeviceQueueFamilyProperties;
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07002437
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002438 if (instance == VK_NULL_HANDLE) {
2439 return NULL;
2440 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002441
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002442 PFN_vkVoidFunction addr;
2443
2444 layer_data *my_data;
2445 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2446 VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
2447 addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
2448 if (addr) {
2449 return addr;
2450 }
Ian Elliott68124ac2015-10-07 16:18:35 -06002451
Ian Elliotta983e9a2015-12-22 12:18:12 -07002452#ifdef VK_USE_PLATFORM_ANDROID_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002453 if (my_data->instanceMap.size() != 0 &&
2454 my_data->instanceMap[instance].androidSurfaceExtensionEnabled)
2455 {
2456 if (!strcmp("vkCreateAndroidSurfaceKHR", funcName))
2457 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateAndroidSurfaceKHR);
2458 }
Ian Elliotta983e9a2015-12-22 12:18:12 -07002459#endif // VK_USE_PLATFORM_ANDROID_KHR
2460#ifdef VK_USE_PLATFORM_MIR_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002461 if (my_data->instanceMap.size() != 0 &&
2462 my_data->instanceMap[instance].mirSurfaceExtensionEnabled)
2463 {
2464 if (!strcmp("vkCreateMirSurfaceKHR", funcName))
2465 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateMirSurfaceKHR);
2466 if (!strcmp("vkGetPhysicalDeviceMirPresentationSupportKHR", funcName))
2467 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceMirPresentationSupportKHR);
2468 }
Ian Elliotta983e9a2015-12-22 12:18:12 -07002469#endif // VK_USE_PLATFORM_MIR_KHR
2470#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002471 if (my_data->instanceMap.size() != 0 &&
2472 my_data->instanceMap[instance].waylandSurfaceExtensionEnabled)
2473 {
2474 if (!strcmp("vkCreateWaylandSurfaceKHR", funcName))
2475 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateWaylandSurfaceKHR);
2476 if (!strcmp("vkGetPhysicalDeviceWaylandPresentationSupportKHR", funcName))
2477 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceWaylandPresentationSupportKHR);
2478 }
Ian Elliotta983e9a2015-12-22 12:18:12 -07002479#endif // VK_USE_PLATFORM_WAYLAND_KHR
2480#ifdef VK_USE_PLATFORM_WIN32_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002481 if (my_data->instanceMap.size() != 0 &&
2482 my_data->instanceMap[instance].win32SurfaceExtensionEnabled)
2483 {
2484 if (!strcmp("vkCreateWin32SurfaceKHR", funcName))
2485 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateWin32SurfaceKHR);
2486 if (!strcmp("vkGetPhysicalDeviceWin32PresentationSupportKHR", funcName))
2487 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceWin32PresentationSupportKHR);
2488 }
Ian Elliotta983e9a2015-12-22 12:18:12 -07002489#endif // VK_USE_PLATFORM_WIN32_KHR
2490#ifdef VK_USE_PLATFORM_XCB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002491 if (my_data->instanceMap.size() != 0 &&
2492 my_data->instanceMap[instance].xcbSurfaceExtensionEnabled)
2493 {
2494 if (!strcmp("vkCreateXcbSurfaceKHR", funcName))
2495 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateXcbSurfaceKHR);
2496 if (!strcmp("vkGetPhysicalDeviceXcbPresentationSupportKHR", funcName))
2497 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceXcbPresentationSupportKHR);
2498 }
Ian Elliotta983e9a2015-12-22 12:18:12 -07002499#endif // VK_USE_PLATFORM_XCB_KHR
2500#ifdef VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002501 if (my_data->instanceMap.size() != 0 &&
2502 my_data->instanceMap[instance].xlibSurfaceExtensionEnabled)
2503 {
2504 if (!strcmp("vkCreateXlibSurfaceKHR", funcName))
2505 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateXlibSurfaceKHR);
2506 if (!strcmp("vkGetPhysicalDeviceXlibPresentationSupportKHR", funcName))
2507 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceXlibPresentationSupportKHR);
2508 }
Ian Elliotta983e9a2015-12-22 12:18:12 -07002509#endif // VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002510 if (my_data->instanceMap.size() != 0 &&
2511 my_data->instanceMap[instance].surfaceExtensionEnabled)
2512 {
2513 if (!strcmp("vkDestroySurfaceKHR", funcName))
2514 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySurfaceKHR);
2515 if (!strcmp("vkGetPhysicalDeviceSurfaceSupportKHR", funcName))
2516 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceSupportKHR);
2517 if (!strcmp("vkGetPhysicalDeviceSurfaceCapabilitiesKHR", funcName))
2518 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
2519 if (!strcmp("vkGetPhysicalDeviceSurfaceFormatsKHR", funcName))
2520 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceFormatsKHR);
2521 if (!strcmp("vkGetPhysicalDeviceSurfacePresentModesKHR", funcName))
2522 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfacePresentModesKHR);
2523 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002524
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002525 if (pTable->GetInstanceProcAddr == NULL)
2526 return NULL;
2527 return pTable->GetInstanceProcAddr(instance, funcName);
2528}
2529