blob: 23b341cd7208921a3a44f96bd18c09d883bf65d3 [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 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -06006 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
Ian Elliott0b4d6242015-09-22 10:51:24 -06009 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060010 * http://www.apache.org/licenses/LICENSE-2.0
Ian Elliott0b4d6242015-09-22 10:51:24 -060011 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060012 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
Ian Elliott0b4d6242015-09-22 10:51:24 -060017 *
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060018 * Author: Ian Elliott <ian@lunarg.com>
Ian Elliott578e7e22016-01-05 14:03:16 -070019 * Author: Ian Elliott <ianelliott@google.com>
Ian Elliott0b4d6242015-09-22 10:51:24 -060020 */
21
Jeremy Hayes9de0bd72016-04-13 11:57:20 -060022#include <mutex>
Ian Elliottd8c5db12015-10-07 11:32:31 -060023#include <stdio.h>
24#include <string.h>
Mark Lobodzinskib49b6e52015-11-26 10:59:58 -070025#include <vk_loader_platform.h>
Cody Northropd08141b2016-02-01 09:52:07 -070026#include <vulkan/vk_icd.h>
Ian Elliott0b4d6242015-09-22 10:51:24 -060027#include "swapchain.h"
Tobin Ehlis711ff312015-10-29 12:58:13 -060028#include "vk_layer_extension_utils.h"
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070029#include "vk_enum_string_helper.h"
Mark Lobodzinski1079e1b2016-03-15 14:21:59 -060030#include "vk_layer_utils.h"
Ian Elliott68124ac2015-10-07 16:18:35 -060031
Chia-I Wu516b5082016-04-28 11:27:46 +080032namespace swapchain {
33
Jeremy Hayes9de0bd72016-04-13 11:57:20 -060034static std::mutex global_lock;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070035
Ian Elliott0b4d6242015-09-22 10:51:24 -060036// The following is for logging error messages:
Ian Elliott68124ac2015-10-07 16:18:35 -060037static std::unordered_map<void *, layer_data *> layer_data_map;
Ian Elliott0b4d6242015-09-22 10:51:24 -060038
Jon Ashburn5484e0c2016-03-08 17:48:44 -070039static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -070040
Chia-I Wu40e25e72016-04-28 14:12:27 +080041static const VkLayerProperties swapchain_layer = {
Jon Ashburndc9111c2016-03-22 12:57:13 -060042 "VK_LAYER_LUNARG_swapchain", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer",
Chia-I Wu40e25e72016-04-28 14:12:27 +080043};
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -070044
Mark Youngaa1aa3a2016-07-05 16:41:50 -060045static void checkDeviceRegisterExtensions(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
46 VkDevice device) {
Ian Elliott0b4d6242015-09-22 10:51:24 -060047 uint32_t i;
Jon Ashburn5484e0c2016-03-08 17:48:44 -070048 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070049 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -060050
Ian Elliott77f46ca2016-05-05 14:10:49 -060051 SwpPhysicalDevice *pPhysicalDevice = NULL;
52 {
53 auto it = my_instance_data->physicalDeviceMap.find(physicalDevice);
54 pPhysicalDevice = (it == my_instance_data->physicalDeviceMap.end()) ? NULL : &it->second;
55 }
Ian Elliott0b4d6242015-09-22 10:51:24 -060056 if (pPhysicalDevice) {
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070057 my_device_data->deviceMap[device].pPhysicalDevice = pPhysicalDevice;
58 pPhysicalDevice->pDevice = &my_device_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -060059 } else {
Ian Elliott07adb112016-01-05 12:51:03 -070060 // TBD: Should we leave error in (since Swapchain really needs this
61 // link)?
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070062 log_msg(my_instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
Jon Ashburn5484e0c2016-03-08 17:48:44 -070063 (uint64_t)physicalDevice, __LINE__, SWAPCHAIN_INVALID_HANDLE, "Swapchain",
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070064 "vkCreateDevice() called with a non-valid VkPhysicalDevice.");
Ian Elliott0b4d6242015-09-22 10:51:24 -060065 }
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070066 my_device_data->deviceMap[device].device = device;
Ian Elliott427058f2015-12-29 16:45:49 -070067 my_device_data->deviceMap[device].swapchainExtensionEnabled = false;
Ian Elliott0b4d6242015-09-22 10:51:24 -060068
69 // Record whether the WSI device extension was enabled for this VkDevice.
70 // No need to check if the extension was advertised by
71 // vkEnumerateDeviceExtensionProperties(), since the loader handles that.
Jon Ashburnf19916e2016-01-11 13:12:43 -070072 for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070073 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
Ian Elliott0b4d6242015-09-22 10:51:24 -060074
Ian Elliott427058f2015-12-29 16:45:49 -070075 my_device_data->deviceMap[device].swapchainExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -060076 }
77 }
78}
79
Mark Youngaa1aa3a2016-07-05 16:41:50 -060080static void checkInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
Ian Elliott0b4d6242015-09-22 10:51:24 -060081 uint32_t i;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070082 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -060083
Ian Elliott1dcd1092015-11-17 17:29:40 -070084 // Remember this instance, and whether the VK_KHR_surface extension
Ian Elliott0b4d6242015-09-22 10:51:24 -060085 // was enabled for it:
Tobin Ehlis711ff312015-10-29 12:58:13 -060086 my_data->instanceMap[instance].instance = instance;
Ian Elliott1cb77a62015-12-29 16:44:39 -070087 my_data->instanceMap[instance].surfaceExtensionEnabled = false;
Petros Bantolas2b40be72016-04-15 11:02:59 +010088 my_data->instanceMap[instance].displayExtensionEnabled = false;
Ian Elliott8dffaf32016-01-04 14:10:30 -070089#ifdef VK_USE_PLATFORM_ANDROID_KHR
90 my_data->instanceMap[instance].androidSurfaceExtensionEnabled = false;
91#endif // VK_USE_PLATFORM_ANDROID_KHR
92#ifdef VK_USE_PLATFORM_MIR_KHR
93 my_data->instanceMap[instance].mirSurfaceExtensionEnabled = false;
94#endif // VK_USE_PLATFORM_MIR_KHR
95#ifdef VK_USE_PLATFORM_WAYLAND_KHR
96 my_data->instanceMap[instance].waylandSurfaceExtensionEnabled = false;
97#endif // VK_USE_PLATFORM_WAYLAND_KHR
98#ifdef VK_USE_PLATFORM_WIN32_KHR
99 my_data->instanceMap[instance].win32SurfaceExtensionEnabled = false;
100#endif // VK_USE_PLATFORM_WIN32_KHR
101#ifdef VK_USE_PLATFORM_XCB_KHR
102 my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = false;
103#endif // VK_USE_PLATFORM_XCB_KHR
104#ifdef VK_USE_PLATFORM_XLIB_KHR
105 my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = false;
106#endif // VK_USE_PLATFORM_XLIB_KHR
107
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600108 // Look for one or more debug report create info structures, and copy the
109 // callback(s) for each one found (for use by vkDestroyInstance)
110 layer_copy_tmp_callbacks(pCreateInfo->pNext, &my_data->num_tmp_callbacks, &my_data->tmp_dbg_create_infos,
111 &my_data->tmp_callbacks);
112
Ian Elliott0b4d6242015-09-22 10:51:24 -0600113 // Record whether the WSI instance extension was enabled for this
114 // VkInstance. No need to check if the extension was advertised by
115 // vkEnumerateInstanceExtensionProperties(), since the loader handles that.
Jon Ashburnf19916e2016-01-11 13:12:43 -0700116 for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700117 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600118
Ian Elliott1cb77a62015-12-29 16:44:39 -0700119 my_data->instanceMap[instance].surfaceExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600120 }
Petros Bantolas2b40be72016-04-15 11:02:59 +0100121 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_EXTENSION_NAME) == 0) {
122
123 my_data->instanceMap[instance].displayExtensionEnabled = true;
124 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700125#ifdef VK_USE_PLATFORM_ANDROID_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700126 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700127
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700128 my_data->instanceMap[instance].androidSurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800129 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700130#endif // VK_USE_PLATFORM_ANDROID_KHR
131#ifdef VK_USE_PLATFORM_MIR_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700132 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_MIR_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700133
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700134 my_data->instanceMap[instance].mirSurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800135 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700136#endif // VK_USE_PLATFORM_MIR_KHR
137#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700138 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700139
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700140 my_data->instanceMap[instance].waylandSurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800141 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700142#endif // VK_USE_PLATFORM_WAYLAND_KHR
143#ifdef VK_USE_PLATFORM_WIN32_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700144 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700145
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700146 my_data->instanceMap[instance].win32SurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800147 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700148#endif // VK_USE_PLATFORM_WIN32_KHR
149#ifdef VK_USE_PLATFORM_XCB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700150 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700151
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700152 my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800153 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700154#endif // VK_USE_PLATFORM_XCB_KHR
155#ifdef VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700156 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700157
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700158 my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = true;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700159 }
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800160#endif // VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700161 }
162}
163
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700164#include "vk_dispatch_table_helper.h"
Mark Lobodzinski1079e1b2016-03-15 14:21:59 -0600165static void init_swapchain(layer_data *my_data, const VkAllocationCallbacks *pAllocator) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600166
Mark Lobodzinski1079e1b2016-03-15 14:21:59 -0600167 layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_swapchain");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700168}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600169
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700170static const char *surfaceTransformStr(VkSurfaceTransformFlagBitsKHR value) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700171 // Return a string corresponding to the value:
172 return string_VkSurfaceTransformFlagBitsKHR(value);
173}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600174
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700175static const char *surfaceCompositeAlphaStr(VkCompositeAlphaFlagBitsKHR value) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700176 // Return a string corresponding to the value:
177 return string_VkCompositeAlphaFlagBitsKHR(value);
178}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600179
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700180static const char *presentModeStr(VkPresentModeKHR value) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700181 // Return a string corresponding to the value:
182 return string_VkPresentModeKHR(value);
183}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600184
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700185static const char *sharingModeStr(VkSharingMode value) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700186 // Return a string corresponding to the value:
187 return string_VkSharingMode(value);
188}
Ian Elliott07adb112016-01-05 12:51:03 -0700189
Chia-I Wufccbfe42016-04-28 14:01:30 +0800190VKAPI_ATTR VkResult VKAPI_CALL
191CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700192 VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600193
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700194 assert(chain_info->u.pLayerInfo);
195 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700196 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700197 if (fpCreateInstance == NULL) {
198 return VK_ERROR_INITIALIZATION_FAILED;
199 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700200
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700201 // Advance the link info for the next element on the chain
202 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700203
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700204 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
205 if (result != VK_SUCCESS) {
206 return result;
207 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700208
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700209 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
Chia-I Wua6737532016-04-28 16:04:15 +0800210 my_data->instance = *pInstance;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700211 my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
212 layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700213
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700214 my_data->report_data = debug_report_create_instance(my_data->instance_dispatch_table, *pInstance,
215 pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700216
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700217 // Call the following function after my_data is initialized:
Mark Youngaa1aa3a2016-07-05 16:41:50 -0600218 checkInstanceRegisterExtensions(pCreateInfo, *pInstance);
Mark Lobodzinski1079e1b2016-03-15 14:21:59 -0600219 init_swapchain(my_data, pAllocator);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700220
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700221 return result;
222}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700223
Chia-I Wufccbfe42016-04-28 14:01:30 +0800224VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700225 dispatch_key key = get_dispatch_key(instance);
226 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600227 SwpInstance *pInstance = NULL;
228 {
229 auto it = my_data->instanceMap.find(instance);
230 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
231 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700232
Ian Elliott32311832016-02-04 08:17:18 -0700233 // Call down the call chain:
234 my_data->instance_dispatch_table->DestroyInstance(instance, pAllocator);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700235
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600236 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott32311832016-02-04 08:17:18 -0700237
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600238 // Enable the temporary callback(s) here to catch cleanup issues:
239 bool callback_setup = false;
240 if (my_data->num_tmp_callbacks > 0) {
241 if (!layer_enable_tmp_callbacks(my_data->report_data, my_data->num_tmp_callbacks, my_data->tmp_dbg_create_infos,
242 my_data->tmp_callbacks)) {
243 callback_setup = true;
244 }
245 }
246
Ian Elliott32311832016-02-04 08:17:18 -0700247 // Do additional internal cleanup:
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700248 if (pInstance) {
249 // Delete all of the SwpPhysicalDevice's, SwpSurface's, and the
250 // SwpInstance associated with this instance:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700251 for (auto it = pInstance->physicalDevices.begin(); it != pInstance->physicalDevices.end(); it++) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700252
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700253 // Free memory that was allocated for/by this SwpPhysicalDevice:
254 SwpPhysicalDevice *pPhysicalDevice = it->second;
255 if (pPhysicalDevice) {
Ian Elliott458696a2016-02-04 06:11:17 -0700256 if (pPhysicalDevice->pDevice) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700257 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Ian Elliott458696a2016-02-04 06:11:17 -0700258 "%s() called before all of its associated "
259 "VkDevices were destroyed.",
260 __FUNCTION__);
261 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700262 free(pPhysicalDevice->pSurfaceFormats);
263 free(pPhysicalDevice->pPresentModes);
264 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700265
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700266 // Erase the SwpPhysicalDevice's from the my_data->physicalDeviceMap (which
267 // are simply pointed to by the SwpInstance):
268 my_data->physicalDeviceMap.erase(it->second->physicalDevice);
269 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700270 for (auto it = pInstance->surfaces.begin(); it != pInstance->surfaces.end(); it++) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700271
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700272 // Free memory that was allocated for/by this SwpPhysicalDevice:
273 SwpSurface *pSurface = it->second;
274 if (pSurface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700275 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700276 "%s() called before all of its associated "
277 "VkSurfaceKHRs were destroyed.",
278 __FUNCTION__);
279 }
280 }
281 my_data->instanceMap.erase(instance);
282 }
Mark Lobodzinski3c99d552016-02-04 13:50:23 -0700283
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600284 // Disable and cleanup the temporary callback(s):
285 if (callback_setup) {
286 layer_disable_tmp_callbacks(my_data->report_data, my_data->num_tmp_callbacks, my_data->tmp_callbacks);
287 }
288 if (my_data->num_tmp_callbacks > 0) {
289 layer_free_tmp_callbacks(my_data->tmp_dbg_create_infos, my_data->tmp_callbacks);
290 my_data->num_tmp_callbacks = 0;
291 }
292
Mark Lobodzinski3c99d552016-02-04 13:50:23 -0700293 // Clean up logging callback, if any
294 while (my_data->logging_callback.size() > 0) {
295 VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
296 layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
297 my_data->logging_callback.pop_back();
298 }
299 layer_debug_report_destroy_instance(my_data->report_data);
300
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700301 delete my_data->instance_dispatch_table;
302 layer_data_map.erase(key);
303}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700304
Chia-I Wufccbfe42016-04-28 14:01:30 +0800305VKAPI_ATTR void VKAPI_CALL
306GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount,
307 VkQueueFamilyProperties *pQueueFamilyProperties) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700308 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700309
310 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700311 my_data->instance_dispatch_table->GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount,
312 pQueueFamilyProperties);
Ian Elliott32311832016-02-04 08:17:18 -0700313
314 // Record the result of this query:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600315 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600316 SwpPhysicalDevice *pPhysicalDevice = NULL;
317 {
318 auto it = my_data->physicalDeviceMap.find(physicalDevice);
319 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
320 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700321 if (pPhysicalDevice && pQueueFamilyPropertyCount && !pQueueFamilyProperties) {
Ian Elliott32311832016-02-04 08:17:18 -0700322 pPhysicalDevice->gotQueueFamilyPropertyCount = true;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700323 pPhysicalDevice->numOfQueueFamilies = *pQueueFamilyPropertyCount;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700324 }
325}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700326
327#ifdef VK_USE_PLATFORM_ANDROID_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800328VKAPI_ATTR VkResult VKAPI_CALL
329CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo,
330 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700331 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600332 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700333 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600334 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600335 SwpInstance *pInstance = NULL;
336 {
337 auto it = my_data->instanceMap.find(instance);
338 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
339 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700340
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700341 // Validate that the platform extension was enabled:
Cody Northropd08141b2016-02-01 09:52:07 -0700342 if (pInstance && !pInstance->androidSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700343 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
344 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
345 VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700346 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700347
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700348 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700349 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700350 } else {
351 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700352 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700353 "VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR");
354 }
355 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700356 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700357 }
358 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600359 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700360
Dustin Graves080069b2016-04-05 13:48:15 -0600361 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700362 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700363 result = my_data->instance_dispatch_table->CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600364 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700365
Ian Elliott32311832016-02-04 08:17:18 -0700366 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600367 {
368 auto it = my_data->instanceMap.find(instance);
369 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
370 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700371 if ((result == VK_SUCCESS) && pInstance && pSurface) {
372 // Record the VkSurfaceKHR returned by the ICD:
373 my_data->surfaceMap[*pSurface].surface = *pSurface;
374 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700375 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700376 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
377 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
378 // Point to the associated SwpInstance:
379 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
380 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600381 lock.unlock();
382
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700383 return result;
384 }
385 return VK_ERROR_VALIDATION_FAILED_EXT;
386}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700387#endif // VK_USE_PLATFORM_ANDROID_KHR
388
389#ifdef VK_USE_PLATFORM_MIR_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800390VKAPI_ATTR VkResult VKAPI_CALL
391CreateMirSurfaceKHR(VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
392 VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700393 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600394 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700395 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600396 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600397 SwpInstance *pInstance = NULL;
398 {
399 auto it = my_data->instanceMap.find(instance);
400 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
401 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700402
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700403 // Validate that the platform extension was enabled:
404 if (pInstance && !pInstance->mirSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700405 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
406 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
407 VK_KHR_MIR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700408 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700409
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700410 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700411 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700412 } else {
413 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700414 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700415 "VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR");
416 }
417 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700418 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700419 }
420 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600421 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700422
Dustin Graves080069b2016-04-05 13:48:15 -0600423 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700424 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700425 result = my_data->instance_dispatch_table->CreateMirSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600426 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700427
Ian Elliott32311832016-02-04 08:17:18 -0700428 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600429 {
430 auto it = my_data->instanceMap.find(instance);
431 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
432 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700433 if ((result == VK_SUCCESS) && pInstance && pSurface) {
434 // Record the VkSurfaceKHR returned by the ICD:
435 my_data->surfaceMap[*pSurface].surface = *pSurface;
436 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700437 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700438 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
439 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
440 // Point to the associated SwpInstance:
441 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
442 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600443 lock.unlock();
444
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700445 return result;
446 }
447 return VK_ERROR_VALIDATION_FAILED_EXT;
448}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700449
Chia-I Wufccbfe42016-04-28 14:01:30 +0800450VKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceMirPresentationSupportKHR(VkPhysicalDevice physicalDevice,
451 uint32_t queueFamilyIndex,
452 MirConnection *connection) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700453 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600454 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700455 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600456 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600457 SwpPhysicalDevice *pPhysicalDevice = NULL;
458 {
459 auto it = my_data->physicalDeviceMap.find(physicalDevice);
460 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
461 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700462
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700463 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700464 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->mirSurfaceExtensionEnabled) {
465 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700466 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700467 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
468 VK_KHR_MIR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700469 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700470 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
471 skipCall |=
472 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
473 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700474 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600475 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700476
Dustin Graves080069b2016-04-05 13:48:15 -0600477 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700478 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700479 result = my_data->instance_dispatch_table->GetPhysicalDeviceMirPresentationSupportKHR(physicalDevice, queueFamilyIndex,
480 connection);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700481 }
482 return result;
483}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700484#endif // VK_USE_PLATFORM_MIR_KHR
485
486#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800487VKAPI_ATTR VkResult VKAPI_CALL
488CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
489 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700490 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600491 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700492 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600493 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600494 SwpInstance *pInstance = NULL;
495 {
496 auto it = my_data->instanceMap.find(instance);
497 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
498 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700499
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700500 // Validate that the platform extension was enabled:
501 if (pInstance && !pInstance->waylandSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700502 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
503 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
504 VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700505 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700506
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700507 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700508 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700509 } else {
510 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700511 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700512 "VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR");
513 }
514 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700515 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700516 }
517 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600518 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700519
Dustin Graves080069b2016-04-05 13:48:15 -0600520 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700521 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700522 result = my_data->instance_dispatch_table->CreateWaylandSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600523 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700524
Ian Elliott32311832016-02-04 08:17:18 -0700525 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600526 {
527 auto it = my_data->instanceMap.find(instance);
528 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
529 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700530 if ((result == VK_SUCCESS) && pInstance && pSurface) {
531 // Record the VkSurfaceKHR returned by the ICD:
532 my_data->surfaceMap[*pSurface].surface = *pSurface;
533 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700534 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700535 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
536 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
537 // Point to the associated SwpInstance:
538 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
539 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600540 lock.unlock();
541
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700542 return result;
543 }
544 return VK_ERROR_VALIDATION_FAILED_EXT;
545}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700546
Chia-I Wufccbfe42016-04-28 14:01:30 +0800547VKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,
548 uint32_t queueFamilyIndex,
549 struct wl_display *display) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700550 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600551 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700552 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600553 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600554 SwpPhysicalDevice *pPhysicalDevice = NULL;
555 {
556 auto it = my_data->physicalDeviceMap.find(physicalDevice);
557 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
558 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700559
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700560 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700561 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->waylandSurfaceExtensionEnabled) {
562 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700563 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700564 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
565 VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700566 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700567 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
568 skipCall |=
569 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
570 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700571 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600572 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700573
Dustin Graves080069b2016-04-05 13:48:15 -0600574 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700575 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700576 result = my_data->instance_dispatch_table->GetPhysicalDeviceWaylandPresentationSupportKHR(physicalDevice, queueFamilyIndex,
577 display);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700578 }
579 return result;
580}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700581#endif // VK_USE_PLATFORM_WAYLAND_KHR
582
583#ifdef VK_USE_PLATFORM_WIN32_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800584VKAPI_ATTR VkResult VKAPI_CALL
585CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
586 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700587 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600588 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700589 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600590 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600591 SwpInstance *pInstance = NULL;
592 {
593 auto it = my_data->instanceMap.find(instance);
594 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
595 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700596
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700597 // Validate that the platform extension was enabled:
598 if (pInstance && !pInstance->win32SurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700599 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
600 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
601 VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700602 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700603
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700604 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700605 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700606 } else {
607 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700608 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700609 "VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR");
610 }
611 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700612 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700613 }
614 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600615 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700616
Dustin Graves080069b2016-04-05 13:48:15 -0600617 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700618 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700619 result = my_data->instance_dispatch_table->CreateWin32SurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600620 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700621
Ian Elliott32311832016-02-04 08:17:18 -0700622 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600623 {
624 auto it = my_data->instanceMap.find(instance);
625 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
626 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700627 if ((result == VK_SUCCESS) && pInstance && pSurface) {
628 // Record the VkSurfaceKHR returned by the ICD:
629 my_data->surfaceMap[*pSurface].surface = *pSurface;
630 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700631 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700632 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
633 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
634 // Point to the associated SwpInstance:
635 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
636 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600637 lock.unlock();
638
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700639 return result;
640 }
641 return VK_ERROR_VALIDATION_FAILED_EXT;
642}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700643
Chia-I Wufccbfe42016-04-28 14:01:30 +0800644VKAPI_ATTR VkBool32 VKAPI_CALL
645GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700646 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600647 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700648 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600649 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600650 SwpPhysicalDevice *pPhysicalDevice = NULL;
651 {
652 auto it = my_data->physicalDeviceMap.find(physicalDevice);
653 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
654 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700655
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700656 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700657 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->win32SurfaceExtensionEnabled) {
658 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700659 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700660 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
661 VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700662 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700663 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
664 skipCall |=
665 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
666 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700667 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600668 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700669
Dustin Graves080069b2016-04-05 13:48:15 -0600670 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700671 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700672 result = my_data->instance_dispatch_table->GetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700673 }
674 return result;
675}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700676#endif // VK_USE_PLATFORM_WIN32_KHR
677
678#ifdef VK_USE_PLATFORM_XCB_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800679VKAPI_ATTR VkResult VKAPI_CALL
680CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700681 VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700682 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600683 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700684 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600685 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600686 SwpInstance *pInstance = NULL;
687 {
688 auto it = my_data->instanceMap.find(instance);
689 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
690 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700691
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700692 // Validate that the platform extension was enabled:
693 if (pInstance && !pInstance->xcbSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700694 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
695 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
696 VK_KHR_XCB_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700697 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700698
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700699 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700700 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700701 } else {
702 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700703 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700704 "VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR");
705 }
706 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700707 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700708 }
709 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600710 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700711
Dustin Graves080069b2016-04-05 13:48:15 -0600712 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700713 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700714 result = my_data->instance_dispatch_table->CreateXcbSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600715 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700716
Ian Elliott32311832016-02-04 08:17:18 -0700717 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600718 {
719 auto it = my_data->instanceMap.find(instance);
720 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
721 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700722 if ((result == VK_SUCCESS) && pInstance && pSurface) {
723 // Record the VkSurfaceKHR returned by the ICD:
724 my_data->surfaceMap[*pSurface].surface = *pSurface;
725 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700726 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700727 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
728 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
729 // Point to the associated SwpInstance:
730 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
731 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600732 lock.unlock();
733
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700734 return result;
735 }
736 return VK_ERROR_VALIDATION_FAILED_EXT;
737}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700738
Chia-I Wufccbfe42016-04-28 14:01:30 +0800739VKAPI_ATTR VkBool32 VKAPI_CALL
740GetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex,
741 xcb_connection_t *connection, xcb_visualid_t visual_id) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700742 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600743 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700744 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600745 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600746 SwpPhysicalDevice *pPhysicalDevice = NULL;
747 {
748 auto it = my_data->physicalDeviceMap.find(physicalDevice);
749 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
750 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700751
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700752 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700753 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->xcbSurfaceExtensionEnabled) {
754 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700755 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700756 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
757 VK_KHR_XCB_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700758 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700759 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
760 skipCall |=
761 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
762 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700763 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600764 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700765
Dustin Graves080069b2016-04-05 13:48:15 -0600766 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700767 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700768 result = my_data->instance_dispatch_table->GetPhysicalDeviceXcbPresentationSupportKHR(physicalDevice, queueFamilyIndex,
769 connection, visual_id);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700770 }
771 return result;
772}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700773#endif // VK_USE_PLATFORM_XCB_KHR
774
775#ifdef VK_USE_PLATFORM_XLIB_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800776VKAPI_ATTR VkResult VKAPI_CALL
777CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
778 VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700779 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600780 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700781 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600782 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600783 SwpInstance *pInstance = NULL;
784 {
785 auto it = my_data->instanceMap.find(instance);
786 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
787 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700788
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700789 // Validate that the platform extension was enabled:
790 if (pInstance && !pInstance->xlibSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700791 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
792 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
793 VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700794 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700795
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700796 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700797 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700798 } else {
799 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700800 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700801 "VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR");
802 }
803 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700804 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700805 }
806 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600807 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700808
Dustin Graves080069b2016-04-05 13:48:15 -0600809 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700810 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700811 result = my_data->instance_dispatch_table->CreateXlibSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600812 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700813
Ian Elliott32311832016-02-04 08:17:18 -0700814 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600815 {
816 auto it = my_data->instanceMap.find(instance);
817 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
818 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700819 if ((result == VK_SUCCESS) && pInstance && pSurface) {
820 // Record the VkSurfaceKHR returned by the ICD:
821 my_data->surfaceMap[*pSurface].surface = *pSurface;
822 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700823 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700824 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
825 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
826 // Point to the associated SwpInstance:
827 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
828 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600829 lock.unlock();
830
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700831 return result;
832 }
833 return VK_ERROR_VALIDATION_FAILED_EXT;
834}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700835
Chia-I Wufccbfe42016-04-28 14:01:30 +0800836VKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
837 uint32_t queueFamilyIndex,
838 Display *dpy, VisualID visualID) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700839 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600840 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700841 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600842 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600843 SwpPhysicalDevice *pPhysicalDevice = NULL;
844 {
845 auto it = my_data->physicalDeviceMap.find(physicalDevice);
846 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
847 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700848
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700849 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700850 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->xlibSurfaceExtensionEnabled) {
851 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700852 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700853 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
854 VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700855 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700856 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
857 skipCall |=
858 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
859 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700860 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600861 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700862
Dustin Graves080069b2016-04-05 13:48:15 -0600863 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700864 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700865 result = my_data->instance_dispatch_table->GetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex,
866 dpy, visualID);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700867 }
868 return result;
869}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700870#endif // VK_USE_PLATFORM_XLIB_KHR
871
Petros Bantolas2b40be72016-04-15 11:02:59 +0100872VKAPI_ATTR VkResult VKAPI_CALL
873GetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkDisplayPropertiesKHR *pProperties) {
874 VkResult result = VK_SUCCESS;
875 bool skipCall = false;
876 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
877 std::unique_lock<std::mutex> lock(global_lock);
878 SwpPhysicalDevice *pPhysicalDevice = NULL;
879 {
880 auto it = my_data->physicalDeviceMap.find(physicalDevice);
881 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
882 }
883
884 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
885 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
886 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
887 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
888 VK_KHR_DISPLAY_EXTENSION_NAME);
889 }
890
891 if (!pPropertyCount) {
892 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pPropertyCount");
893 }
Jon Ashburne699f442016-06-30 09:01:27 -0600894 // TODO add check for the count being consistent
Petros Bantolas2b40be72016-04-15 11:02:59 +0100895 lock.unlock();
896
897 if (!skipCall) {
898 result = my_data->instance_dispatch_table->GetPhysicalDeviceDisplayPropertiesKHR(physicalDevice, pPropertyCount, pProperties);
899 return result;
900 }
901 return VK_ERROR_VALIDATION_FAILED_EXT;
902}
903
Petros Bantolas2b40be72016-04-15 11:02:59 +0100904VKAPI_ATTR VkResult VKAPI_CALL
905GetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkDisplayPlanePropertiesKHR *pProperties) {
906 VkResult result = VK_SUCCESS;
907 bool skipCall = false;
908 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
909 std::unique_lock<std::mutex> lock(global_lock);
910 SwpPhysicalDevice *pPhysicalDevice = NULL;
911 {
912 auto it = my_data->physicalDeviceMap.find(physicalDevice);
913 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
914 }
915
916 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
917 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
918 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
919 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
920 VK_KHR_DISPLAY_EXTENSION_NAME);
921 }
922
923 if (!pPropertyCount) {
924 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pPropertyCount");
925 }
Jon Ashburne699f442016-06-30 09:01:27 -0600926 // TODO add check for the count being consistent
Petros Bantolas2b40be72016-04-15 11:02:59 +0100927 lock.unlock();
928
929 if (!skipCall) {
930 result = my_data->instance_dispatch_table->GetPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, pPropertyCount, pProperties);
931
932 lock.lock();
933 if (!pPhysicalDevice->gotDisplayPlanePropertyCount)
934 {
935 pPhysicalDevice->displayPlanePropertyCount = *pPropertyCount;
936 pPhysicalDevice->gotDisplayPlanePropertyCount = true;
937 }
Jon Ashburne699f442016-06-30 09:01:27 -0600938 // TODO store the properties for later checks
Petros Bantolas2b40be72016-04-15 11:02:59 +0100939 lock.unlock();
940
941 return result;
942 }
943 return VK_ERROR_VALIDATION_FAILED_EXT;
944}
945
946VKAPI_ATTR VkResult VKAPI_CALL
947GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays) {
948 VkResult result = VK_SUCCESS;
949 bool skipCall = false;
950 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
951 std::unique_lock<std::mutex> lock(global_lock);
952 SwpPhysicalDevice *pPhysicalDevice = NULL;
953 {
954 auto it = my_data->physicalDeviceMap.find(physicalDevice);
955 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
956 }
957
958 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
959 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
960 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
961 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
962 VK_KHR_DISPLAY_EXTENSION_NAME);
963 }
964
965 if (!pDisplayCount) {
966 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pDisplayCount");
967 }
Jon Ashburne699f442016-06-30 09:01:27 -0600968 // TODO add check for the count being consistent
Petros Bantolas2b40be72016-04-15 11:02:59 +0100969
Jon Ashburn5e026df2016-06-15 08:19:07 -0600970 if (!pPhysicalDevice->gotDisplayPlanePropertyCount)
Petros Bantolas2b40be72016-04-15 11:02:59 +0100971 {
972 LOG_WARNING(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
973 SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY,
974 "Potential problem with calling %s() without first querying vkGetPhysicalDeviceDisplayPlanePropertiesKHR.",
975 __FUNCTION__);
976 }
977
Jon Ashburn1e857902016-07-01 10:08:31 -0600978 if (pPhysicalDevice->gotDisplayPlanePropertyCount && planeIndex >= pPhysicalDevice->displayPlanePropertyCount)
Petros Bantolas2b40be72016-04-15 11:02:59 +0100979 {
980 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
981 SWAPCHAIN_PLANE_INDEX_TOO_LARGE,
982 "%s(): %s must be in the range [0, %d] that was returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR. Do you have the plane index hardcoded?",
983 __FUNCTION__,
984 "planeIndex",
Jon Ashburn5e026df2016-06-15 08:19:07 -0600985 pPhysicalDevice->displayPlanePropertyCount - 1);
Petros Bantolas2b40be72016-04-15 11:02:59 +0100986 }
987 lock.unlock();
988
989 if (!skipCall) {
990 result = my_data->instance_dispatch_table->GetDisplayPlaneSupportedDisplaysKHR(physicalDevice, planeIndex, pDisplayCount, pDisplays);
991
992 return result;
993 }
Jon Ashburne699f442016-06-30 09:01:27 -0600994 // TODO validate the returned display objects
Petros Bantolas2b40be72016-04-15 11:02:59 +0100995 return VK_ERROR_VALIDATION_FAILED_EXT;
996}
997
998VKAPI_ATTR VkResult VKAPI_CALL
999GetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties) {
1000 VkResult result = VK_SUCCESS;
1001 bool skipCall = false;
1002 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1003 std::unique_lock<std::mutex> lock(global_lock);
1004 SwpPhysicalDevice *pPhysicalDevice = NULL;
1005 {
1006 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1007 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1008 }
1009
1010 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
1011 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1012 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1013 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1014 VK_KHR_DISPLAY_EXTENSION_NAME);
1015 }
1016
1017 if (!pPropertyCount) {
1018 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pPropertyCount");
1019 }
Jon Ashburne699f442016-06-30 09:01:27 -06001020 // TODO add check for the count being consistent
Petros Bantolas2b40be72016-04-15 11:02:59 +01001021 lock.unlock();
1022
1023 if (!skipCall) {
1024 result = my_data->instance_dispatch_table->GetDisplayModePropertiesKHR(physicalDevice, display, pPropertyCount, pProperties);
1025 return result;
1026 }
Jon Ashburne699f442016-06-30 09:01:27 -06001027 // TODO store the displayMode for later checking
Petros Bantolas2b40be72016-04-15 11:02:59 +01001028 return VK_ERROR_VALIDATION_FAILED_EXT;
1029}
1030
1031VKAPI_ATTR VkResult VKAPI_CALL
1032CreateDisplayModeKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode) {
1033 VkResult result = VK_SUCCESS;
1034 bool skipCall = false;
1035 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1036 std::unique_lock<std::mutex> lock(global_lock);
1037 SwpPhysicalDevice *pPhysicalDevice = NULL;
1038 {
1039 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1040 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1041 }
1042
1043 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
1044 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1045 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1046 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1047 VK_KHR_DISPLAY_EXTENSION_NAME);
1048 }
1049
1050 if (!pCreateInfo) {
1051 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pCreateInfo");
1052 }
1053 lock.unlock();
1054
Jon Ashburne699f442016-06-30 09:01:27 -06001055 // TODO more validation checks needed
Petros Bantolas2b40be72016-04-15 11:02:59 +01001056 if (!skipCall) {
1057 result = my_data->instance_dispatch_table->CreateDisplayModeKHR(physicalDevice, display, pCreateInfo, pAllocator, pMode);
1058 return result;
1059 }
1060
1061 return VK_ERROR_VALIDATION_FAILED_EXT;
1062}
1063
1064VKAPI_ATTR VkResult VKAPI_CALL
1065GetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR* pCapabilities) {
1066 VkResult result = VK_SUCCESS;
1067 bool skipCall = false;
1068 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1069 std::unique_lock<std::mutex> lock(global_lock);
1070 SwpPhysicalDevice *pPhysicalDevice = NULL;
1071 {
1072 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1073 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1074 }
1075
1076 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
1077 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1078 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1079 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1080 VK_KHR_DISPLAY_EXTENSION_NAME);
1081 }
1082
Jon Ashburn5e026df2016-06-15 08:19:07 -06001083 if (!pPhysicalDevice->gotDisplayPlanePropertyCount)
Petros Bantolas2b40be72016-04-15 11:02:59 +01001084 {
1085 LOG_WARNING(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
1086 SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY,
1087 "Potential problem with calling %s() without first querying vkGetPhysicalDeviceDisplayPlanePropertiesKHR.",
1088 __FUNCTION__);
1089 }
1090
Jon Ashburn5e026df2016-06-15 08:19:07 -06001091 if (pPhysicalDevice->gotDisplayPlanePropertyCount && planeIndex >= pPhysicalDevice->displayPlanePropertyCount)
Petros Bantolas2b40be72016-04-15 11:02:59 +01001092 {
1093 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
1094 SWAPCHAIN_PLANE_INDEX_TOO_LARGE,
1095 "%s(): %s must be in the range [0, %d] that was returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR. Do you have the plane index hardcoded?",
1096 __FUNCTION__,
1097 "planeIndex",
Jon Ashburn5e026df2016-06-15 08:19:07 -06001098 pPhysicalDevice->displayPlanePropertyCount - 1);
Petros Bantolas2b40be72016-04-15 11:02:59 +01001099 }
1100
1101 if (!pCapabilities) {
1102 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pCapabilities");
1103 }
1104 lock.unlock();
1105
1106 if (!skipCall) {
1107 result = my_data->instance_dispatch_table->GetDisplayPlaneCapabilitiesKHR(physicalDevice, mode, planeIndex, pCapabilities);
1108 return result;
1109 }
1110
1111 return VK_ERROR_VALIDATION_FAILED_EXT;
1112}
1113
1114VKAPI_ATTR VkResult VKAPI_CALL
1115CreateDisplayPlaneSurfaceKHR(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
1116 VkSurfaceKHR *pSurface) {
1117 VkResult result = VK_SUCCESS;
1118 bool skipCall = false;
1119 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1120 std::unique_lock<std::mutex> lock(global_lock);
1121 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
1122
1123 // Validate that the platform extension was enabled:
1124 if (pInstance && !pInstance->displayExtensionEnabled) {
1125 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1126 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1127 VK_KHR_DISPLAY_EXTENSION_NAME);
1128 }
1129
1130 if (!pCreateInfo) {
1131 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
1132 } else {
1133 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR) {
1134 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
1135 "VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR");
1136 }
1137 if (pCreateInfo->pNext != NULL) {
1138 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
1139 }
1140 }
1141
Jon Ashburne699f442016-06-30 09:01:27 -06001142 // TODO more validation checks
Petros Bantolas2b40be72016-04-15 11:02:59 +01001143 if (!skipCall) {
1144 // Call down the call chain:
1145 lock.unlock();
1146 result = my_data->instance_dispatch_table->CreateDisplayPlaneSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
1147 lock.lock();
1148
1149 // Obtain this pointer again after locking:
1150 pInstance = &(my_data->instanceMap[instance]);
1151 if ((result == VK_SUCCESS) && pInstance && pSurface) {
1152 // Record the VkSurfaceKHR returned by the ICD:
1153 my_data->surfaceMap[*pSurface].surface = *pSurface;
1154 my_data->surfaceMap[*pSurface].pInstance = pInstance;
1155 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
1156 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
1157 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
1158 // Point to the associated SwpInstance:
1159 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
1160 }
1161 lock.unlock();
1162 return result;
1163 }
1164 return VK_ERROR_VALIDATION_FAILED_EXT;
1165}
1166
Chia-I Wufccbfe42016-04-28 14:01:30 +08001167VKAPI_ATTR void VKAPI_CALL
1168DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) {
Dustin Graves080069b2016-04-05 13:48:15 -06001169 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001170 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001171 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001172 SwpSurface *pSurface = NULL;
1173 {
1174 auto it = my_data->surfaceMap.find(surface);
1175 pSurface = (it == my_data->surfaceMap.end()) ? NULL : &it->second;
1176 }
1177 SwpInstance *pInstance = NULL;
1178 {
1179 auto it = my_data->instanceMap.find(instance);
1180 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
1181 }
Ian Elliottf6b8c782016-04-29 13:03:17 -06001182
1183 // Validate that the platform extension was enabled:
1184 if (pInstance && !pInstance->surfaceExtensionEnabled) {
1185 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1186 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1187 VK_KHR_SURFACE_EXTENSION_NAME);
1188 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001189
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001190 // Regardless of skipCall value, do some internal cleanup:
1191 if (pSurface) {
1192 // Delete the SwpSurface associated with this surface:
1193 if (pSurface->pInstance) {
1194 pSurface->pInstance->surfaces.erase(surface);
1195 }
1196 if (!pSurface->swapchains.empty()) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001197 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001198 "%s() called before all of its associated "
1199 "VkSwapchainKHRs were destroyed.",
1200 __FUNCTION__);
1201 // Empty and then delete all SwpSwapchain's
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001202 for (auto it = pSurface->swapchains.begin(); it != pSurface->swapchains.end(); it++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001203 // Delete all SwpImage's
1204 it->second->images.clear();
1205 // In case the swapchain's device hasn't been destroyed yet
1206 // (which isn't likely, but is possible), delete its
1207 // association with this swapchain (i.e. so we can't point to
1208 // this swpchain from that device, later on):
1209 if (it->second->pDevice) {
1210 it->second->pDevice->swapchains.clear();
1211 }
1212 }
1213 pSurface->swapchains.clear();
1214 }
1215 if ((pAllocator != NULL) != pSurface->usedAllocatorToCreate) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001216 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001217 "%s() called with incompatible pAllocator from when "
1218 "the object was created.",
1219 __FUNCTION__);
1220 }
1221 my_data->surfaceMap.erase(surface);
1222 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001223 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001224
Dustin Graves080069b2016-04-05 13:48:15 -06001225 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001226 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001227 my_data->instance_dispatch_table->DestroySurfaceKHR(instance, surface, pAllocator);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001228 }
1229}
1230
Chia-I Wufccbfe42016-04-28 14:01:30 +08001231VKAPI_ATTR VkResult VKAPI_CALL
1232EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001233 VkResult result = VK_SUCCESS;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001234 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001235
1236 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001237 result = my_data->instance_dispatch_table->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
Ian Elliott32311832016-02-04 08:17:18 -07001238
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001239 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001240 SwpInstance *pInstance = NULL;
1241 {
1242 auto it = my_data->instanceMap.find(instance);
1243 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
1244 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001245 if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices && (*pPhysicalDeviceCount > 0)) {
Ian Elliott32311832016-02-04 08:17:18 -07001246 // Record the VkPhysicalDevices returned by the ICD:
1247 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001248 my_data->physicalDeviceMap[pPhysicalDevices[i]].physicalDevice = pPhysicalDevices[i];
Ian Elliott32311832016-02-04 08:17:18 -07001249 my_data->physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance;
1250 my_data->physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL;
1251 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotQueueFamilyPropertyCount = false;
1252 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotSurfaceCapabilities = false;
1253 my_data->physicalDeviceMap[pPhysicalDevices[i]].surfaceFormatCount = 0;
1254 my_data->physicalDeviceMap[pPhysicalDevices[i]].pSurfaceFormats = NULL;
1255 my_data->physicalDeviceMap[pPhysicalDevices[i]].presentModeCount = 0;
1256 my_data->physicalDeviceMap[pPhysicalDevices[i]].pPresentModes = NULL;
1257 // Point to the associated SwpInstance:
1258 if (pInstance) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001259 pInstance->physicalDevices[pPhysicalDevices[i]] = &my_data->physicalDeviceMap[pPhysicalDevices[i]];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001260 }
1261 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001262 }
Ian Elliotta3c69bc2016-02-04 15:34:59 -07001263 return result;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001264}
1265
Chia-I Wufccbfe42016-04-28 14:01:30 +08001266VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice physicalDevice,
1267 const VkDeviceCreateInfo *pCreateInfo,
1268 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Chia-I Wua6737532016-04-28 16:04:15 +08001269 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001270 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
1271
1272 assert(chain_info->u.pLayerInfo);
1273 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
1274 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Chia-I Wua6737532016-04-28 16:04:15 +08001275 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001276 if (fpCreateDevice == NULL) {
1277 return VK_ERROR_INITIALIZATION_FAILED;
1278 }
1279
1280 // Advance the link info for the next element on the chain
1281 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
1282
1283 VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1284 if (result != VK_SUCCESS) {
1285 return result;
1286 }
1287
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001288 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001289 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
1290
1291 // Setup device dispatch table
1292 my_device_data->device_dispatch_table = new VkLayerDispatchTable;
1293 layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
1294
1295 my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
Mark Youngaa1aa3a2016-07-05 16:41:50 -06001296 checkDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001297
1298 return result;
1299}
1300
Chia-I Wufccbfe42016-04-28 14:01:30 +08001301VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001302 dispatch_key key = get_dispatch_key(device);
1303 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001304
1305 // Call down the call chain:
1306 my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
1307
1308 // Do some internal cleanup:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001309 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001310 SwpDevice *pDevice = NULL;
1311 {
1312 auto it = my_data->deviceMap.find(device);
1313 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1314 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001315 if (pDevice) {
1316 // Delete the SwpDevice associated with this device:
1317 if (pDevice->pPhysicalDevice) {
1318 pDevice->pPhysicalDevice->pDevice = NULL;
1319 }
1320 if (!pDevice->swapchains.empty()) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001321 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001322 "%s() called before all of its associated "
1323 "VkSwapchainKHRs were destroyed.",
1324 __FUNCTION__);
1325 // Empty and then delete all SwpSwapchain's
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001326 for (auto it = pDevice->swapchains.begin(); it != pDevice->swapchains.end(); it++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001327 // Delete all SwpImage's
1328 it->second->images.clear();
1329 // In case the swapchain's surface hasn't been destroyed yet
1330 // (which is likely) delete its association with this swapchain
1331 // (i.e. so we can't point to this swpchain from that surface,
1332 // later on):
1333 if (it->second->pSurface) {
1334 it->second->pSurface->swapchains.clear();
1335 }
1336 }
1337 pDevice->swapchains.clear();
1338 }
1339 my_data->deviceMap.erase(device);
1340 }
1341 delete my_data->device_dispatch_table;
1342 layer_data_map.erase(key);
1343}
1344
Chia-I Wufccbfe42016-04-28 14:01:30 +08001345VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
1346 uint32_t queueFamilyIndex, VkSurfaceKHR surface,
1347 VkBool32 *pSupported) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001348 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001349 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001350 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001351 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001352 SwpPhysicalDevice *pPhysicalDevice = NULL;
1353 {
1354 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1355 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1356 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001357
1358 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001359 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1360 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001361 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001362 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1363 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001364 }
1365 if (!pPhysicalDevice->gotQueueFamilyPropertyCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001366 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, "VkPhysicalDevice",
1367 SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES, "%s() called before calling the "
1368 "vkGetPhysicalDeviceQueueFamilyProperties "
1369 "function.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001370 __FUNCTION__);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001371 } else if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
1372 skipCall |=
1373 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
1374 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001375 }
1376 if (!pSupported) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001377 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSupported");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001378 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001379 lock.unlock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001380
Dustin Graves080069b2016-04-05 13:48:15 -06001381 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001382 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001383 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface,
1384 pSupported);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001385 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001386
Ian Elliott32311832016-02-04 08:17:18 -07001387 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001388 {
1389 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1390 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1391 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001392 if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
1393 // Record the result of this query:
1394 SwpInstance *pInstance = pPhysicalDevice->pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001395 SwpSurface *pSurface = (pInstance) ? pInstance->surfaces[surface] : NULL;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001396 if (pSurface) {
1397 pPhysicalDevice->supportedSurfaces[surface] = pSurface;
1398 if (!pSurface->numQueueFamilyIndexSupport) {
1399 if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001400 pSurface->pQueueFamilyIndexSupport =
1401 (VkBool32 *)malloc(pPhysicalDevice->numOfQueueFamilies * sizeof(VkBool32));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001402 if (pSurface->pQueueFamilyIndexSupport != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001403 pSurface->numQueueFamilyIndexSupport = pPhysicalDevice->numOfQueueFamilies;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001404 }
1405 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001406 }
1407 if (pSurface->numQueueFamilyIndexSupport) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001408 pSurface->pQueueFamilyIndexSupport[queueFamilyIndex] = *pSupported;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001409 }
1410 }
1411 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001412 lock.unlock();
1413
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001414 return result;
1415 }
1416 return VK_ERROR_VALIDATION_FAILED_EXT;
1417}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001418
Chia-I Wufccbfe42016-04-28 14:01:30 +08001419VKAPI_ATTR VkResult VKAPI_CALL
1420GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
1421 VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001422 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001423 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001424 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001425 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001426 SwpPhysicalDevice *pPhysicalDevice = NULL;
1427 {
1428 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1429 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1430 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001431
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001432 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001433 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1434 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001435 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001436 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1437 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001438 }
1439 if (!pSurfaceCapabilities) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001440 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceCapabilities");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001441 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001442 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001443
Dustin Graves080069b2016-04-05 13:48:15 -06001444 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001445 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001446 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface,
1447 pSurfaceCapabilities);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001448 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001449
Ian Elliott32311832016-02-04 08:17:18 -07001450 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001451 {
1452 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1453 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1454 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001455 if ((result == VK_SUCCESS) && pPhysicalDevice) {
1456 // Record the result of this query:
1457 pPhysicalDevice->gotSurfaceCapabilities = true;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001458 // FIXME: NEED TO COPY THIS DATA, BECAUSE pSurfaceCapabilities POINTS TO APP-ALLOCATED DATA
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001459 pPhysicalDevice->surfaceCapabilities = *pSurfaceCapabilities;
1460 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001461 lock.unlock();
1462
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001463 return result;
1464 }
1465 return VK_ERROR_VALIDATION_FAILED_EXT;
1466}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001467
Chia-I Wufccbfe42016-04-28 14:01:30 +08001468VKAPI_ATTR VkResult VKAPI_CALL
1469GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount,
1470 VkSurfaceFormatKHR *pSurfaceFormats) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001471 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001472 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001473 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001474 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001475 SwpPhysicalDevice *pPhysicalDevice = NULL;
1476 {
1477 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1478 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1479 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001480
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001481 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001482 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1483 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001484 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001485 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1486 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001487 }
1488 if (!pSurfaceFormatCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001489 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceFormatCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001490 } else if (pPhysicalDevice && pSurfaceFormats) {
1491 // Compare the preliminary value of *pSurfaceFormatCount with the
1492 // value this time:
1493 if (pPhysicalDevice->surfaceFormatCount == 0) {
1494 // Since we haven't recorded a preliminary value of
1495 // *pSurfaceFormatCount, that likely means that the application
1496 // didn't previously call this function with a NULL value of
1497 // pSurfaceFormats:
1498 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
1499 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1500 physicalDevice, "pSurfaceFormatCount", "pSurfaceFormats");
1501 } else if (*pSurfaceFormatCount > pPhysicalDevice->surfaceFormatCount) {
1502 skipCall |= LOG_ERROR_INVALID_COUNT(
1503 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1504 physicalDevice, "pSurfaceFormatCount", "pSurfaceFormats",
1505 *pSurfaceFormatCount, pPhysicalDevice->surfaceFormatCount);
1506 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001507 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001508 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001509
Dustin Graves080069b2016-04-05 13:48:15 -06001510 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001511 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001512 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount,
1513 pSurfaceFormats);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001514 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001515
Ian Elliott32311832016-02-04 08:17:18 -07001516 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001517 {
1518 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1519 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1520 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001521 if ((result == VK_SUCCESS) && pPhysicalDevice && !pSurfaceFormats && pSurfaceFormatCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001522 // Record the result of this preliminary query:
1523 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001524 } else if ((result == VK_SUCCESS) && pPhysicalDevice &&
1525 pSurfaceFormats && pSurfaceFormatCount &&
1526 (*pSurfaceFormatCount > 0)) {
1527 // Record the result of this query:
1528 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
1529 pPhysicalDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)malloc(*pSurfaceFormatCount * sizeof(VkSurfaceFormatKHR));
1530 if (pPhysicalDevice->pSurfaceFormats) {
1531 for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) {
1532 pPhysicalDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001533 }
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001534 } else {
1535 pPhysicalDevice->surfaceFormatCount = 0;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001536 }
1537 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001538 lock.unlock();
1539
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001540 return result;
1541 }
1542 return VK_ERROR_VALIDATION_FAILED_EXT;
1543}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001544
Chia-I Wufccbfe42016-04-28 14:01:30 +08001545VKAPI_ATTR VkResult VKAPI_CALL
1546GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pPresentModeCount,
1547 VkPresentModeKHR *pPresentModes) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001548 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001549 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001550 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001551 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001552 SwpPhysicalDevice *pPhysicalDevice = NULL;
1553 {
1554 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1555 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1556 }
Ian Elliott07adb112016-01-05 12:51:03 -07001557
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001558 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001559 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1560 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001561 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001562 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1563 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001564 }
1565 if (!pPresentModeCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001566 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pPresentModeCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001567 } else if (pPhysicalDevice && pPresentModes) {
1568 // Compare the preliminary value of *pPresentModeCount with the
1569 // value this time:
1570 if (pPhysicalDevice->presentModeCount == 0) {
1571 // Since we haven't recorded a preliminary value of
1572 // *pPresentModeCount, that likely means that the application
1573 // didn't previously call this function with a NULL value of
1574 // pPresentModes:
1575 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
1576 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1577 physicalDevice, "pPresentModeCount", "pPresentModes");
1578 } else if (*pPresentModeCount > pPhysicalDevice->presentModeCount) {
1579 skipCall |= LOG_ERROR_INVALID_COUNT(
1580 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1581 physicalDevice, "pPresentModeCount", "pPresentModes",
1582 *pPresentModeCount, pPhysicalDevice->presentModeCount);
1583 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001584 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001585 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001586
Dustin Graves080069b2016-04-05 13:48:15 -06001587 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001588 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001589 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface,
1590 pPresentModeCount, pPresentModes);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001591 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001592
Ian Elliott32311832016-02-04 08:17:18 -07001593 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001594 {
1595 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1596 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1597 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001598 if ((result == VK_SUCCESS) && pPhysicalDevice && !pPresentModes && pPresentModeCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001599 // Record the result of this preliminary query:
1600 pPhysicalDevice->presentModeCount = *pPresentModeCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001601 } else if ((result == VK_SUCCESS) && pPhysicalDevice &&
1602 pPresentModes && pPresentModeCount &&
1603 (*pPresentModeCount > 0)) {
1604 // Record the result of this query:
1605 pPhysicalDevice->presentModeCount = *pPresentModeCount;
1606 pPhysicalDevice->pPresentModes = (VkPresentModeKHR *)malloc(*pPresentModeCount * sizeof(VkPresentModeKHR));
1607 if (pPhysicalDevice->pPresentModes) {
1608 for (uint32_t i = 0; i < *pPresentModeCount; i++) {
1609 pPhysicalDevice->pPresentModes[i] = pPresentModes[i];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001610 }
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001611 } else {
1612 pPhysicalDevice->presentModeCount = 0;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001613 }
1614 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001615 lock.unlock();
1616
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001617 return result;
1618 }
1619 return VK_ERROR_VALIDATION_FAILED_EXT;
1620}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001621
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001622// This function does the up-front validation work for vkCreateSwapchainKHR(),
Dustin Graves080069b2016-04-05 13:48:15 -06001623// and returns true if a logging callback indicates that the call down the
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001624// chain should be skipped:
Dustin Graves080069b2016-04-05 13:48:15 -06001625static bool validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, VkSwapchainKHR *pSwapchain) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001626 // TODO: Validate cases of re-creating a swapchain (the current code
1627 // assumes a new swapchain is being created).
Dustin Graves080069b2016-04-05 13:48:15 -06001628 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001629 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1630 char fn[] = "vkCreateSwapchainKHR";
Ian Elliott77f46ca2016-05-05 14:10:49 -06001631 SwpDevice *pDevice = NULL;
1632 {
1633 auto it = my_data->deviceMap.find(device);
1634 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1635 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001636
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001637 // Validate that the swapchain extension was enabled:
1638 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001639 return LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1640 "%s() called even though the %s extension was not enabled for this VkDevice.", fn,
1641 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001642 }
1643 if (!pCreateInfo) {
Ian Elliott432a3172016-05-09 12:33:47 -06001644 return LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001645 } else {
1646 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001647 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001648 "VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR");
1649 }
1650 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001651 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001652 }
1653 }
1654 if (!pSwapchain) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001655 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchain");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001656 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001657
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001658 // Keep around a useful pointer to pPhysicalDevice:
1659 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001660
Mark Lobodzinskid40b2db2016-02-25 13:56:57 -07001661 // Validate pCreateInfo values with result of
1662 // vkGetPhysicalDeviceQueueFamilyProperties
1663 if (pPhysicalDevice && pPhysicalDevice->gotQueueFamilyPropertyCount) {
Michael Mc Donnell75ecdb72016-04-03 14:47:51 -07001664 for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001665 if (pCreateInfo->pQueueFamilyIndices[i] >= pPhysicalDevice->numOfQueueFamilies) {
1666 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
1667 "VkPhysicalDevice", pCreateInfo->pQueueFamilyIndices[i],
1668 pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinskid40b2db2016-02-25 13:56:57 -07001669 }
1670 }
1671 }
1672
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001673 // Validate pCreateInfo values with the results of
1674 // vkGetPhysicalDeviceSurfaceCapabilitiesKHR():
1675 if (!pPhysicalDevice || !pPhysicalDevice->gotSurfaceCapabilities) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001676 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001677 "%s() called before calling "
1678 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1679 fn);
1680 } else if (pCreateInfo) {
1681 // Validate pCreateInfo->surface to make sure that
1682 // vkGetPhysicalDeviceSurfaceSupportKHR() reported this as a supported
1683 // surface:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001684 SwpSurface *pSurface = ((pPhysicalDevice) ? pPhysicalDevice->supportedSurfaces[pCreateInfo->surface] : NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001685 if (!pSurface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001686 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001687 "%s() called with pCreateInfo->surface that "
1688 "was not returned by "
1689 "vkGetPhysicalDeviceSurfaceSupportKHR() "
1690 "for the device.",
1691 fn);
1692 }
Ian Elliott4f147fc2016-01-20 08:52:08 -07001693
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001694 // Validate pCreateInfo->minImageCount against
1695 // VkSurfaceCapabilitiesKHR::{min|max}ImageCount:
1696 VkSurfaceCapabilitiesKHR *pCapabilities = &pPhysicalDevice->surfaceCapabilities;
1697 if ((pCreateInfo->minImageCount < pCapabilities->minImageCount) ||
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001698 ((pCapabilities->maxImageCount > 0) && (pCreateInfo->minImageCount > pCapabilities->maxImageCount))) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001699 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001700 SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT, "%s() called with pCreateInfo->minImageCount "
1701 "= %d, which is outside the bounds returned "
1702 "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. "
1703 "minImageCount = %d, maxImageCount = %d).",
1704 fn, pCreateInfo->minImageCount, pCapabilities->minImageCount, pCapabilities->maxImageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001705 }
1706 // Validate pCreateInfo->imageExtent against
1707 // VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
1708 if ((pCapabilities->currentExtent.width == -1) &&
1709 ((pCreateInfo->imageExtent.width < pCapabilities->minImageExtent.width) ||
1710 (pCreateInfo->imageExtent.width > pCapabilities->maxImageExtent.width) ||
1711 (pCreateInfo->imageExtent.height < pCapabilities->minImageExtent.height) ||
1712 (pCreateInfo->imageExtent.height > pCapabilities->maxImageExtent.height))) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001713 skipCall |= LOG_ERROR(
1714 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS,
1715 "%s() called with pCreateInfo->imageExtent = "
1716 "(%d,%d), which is outside the bounds "
1717 "returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): "
1718 "currentExtent = (%d,%d), minImageExtent = "
1719 "(%d,%d), maxImageExtent = (%d,%d).",
1720 fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, pCapabilities->currentExtent.width,
1721 pCapabilities->currentExtent.height, pCapabilities->minImageExtent.width, pCapabilities->minImageExtent.height,
1722 pCapabilities->maxImageExtent.width, pCapabilities->maxImageExtent.height);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001723 }
1724 if ((pCapabilities->currentExtent.width != -1) &&
1725 ((pCreateInfo->imageExtent.width != pCapabilities->currentExtent.width) ||
1726 (pCreateInfo->imageExtent.height != pCapabilities->currentExtent.height))) {
1727 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001728 SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN, "%s() called with pCreateInfo->imageExtent = "
1729 "(%d,%d), which is not equal to the "
1730 "currentExtent = (%d,%d) returned by "
1731 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1732 fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height,
1733 pCapabilities->currentExtent.width, pCapabilities->currentExtent.height);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001734 }
1735 // Validate pCreateInfo->preTransform has one bit set (1st two
1736 // lines of if-statement), which bit is also set in
1737 // VkSurfaceCapabilitiesKHR::supportedTransforms (3rd line of if-statement):
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001738 if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) ||
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001739 !(pCreateInfo->preTransform & pCapabilities->supportedTransforms)) {
1740 // This is an error situation; one for which we'd like to give
1741 // the developer a helpful, multi-line error message. Build it
1742 // up a little at a time, and then log it:
1743 std::string errorString = "";
1744 char str[1024];
1745 // Here's the first part of the message:
1746 sprintf(str, "%s() called with a non-supported "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001747 "pCreateInfo->preTransform (i.e. %s). "
1748 "Supported values are:\n",
1749 fn, surfaceTransformStr(pCreateInfo->preTransform));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001750 errorString += str;
1751 for (int i = 0; i < 32; i++) {
1752 // Build up the rest of the message:
1753 if ((1 << i) & pCapabilities->supportedTransforms) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001754 const char *newStr = surfaceTransformStr((VkSurfaceTransformFlagBitsKHR)(1 << i));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001755 sprintf(str, " %s\n", newStr);
1756 errorString += str;
1757 }
1758 }
1759 // Log the message that we've built up:
Mark Lobodzinskia4cbbcd2016-05-24 15:44:50 -06001760 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1761 reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM, LAYER_NAME,
1762 "%s", errorString.c_str());
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001763 }
1764 // Validate pCreateInfo->compositeAlpha has one bit set (1st two
1765 // lines of if-statement), which bit is also set in
1766 // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha (3rd line of if-statement):
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001767 if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) ||
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001768 !((pCreateInfo->compositeAlpha) & pCapabilities->supportedCompositeAlpha)) {
1769 // This is an error situation; one for which we'd like to give
1770 // the developer a helpful, multi-line error message. Build it
1771 // up a little at a time, and then log it:
1772 std::string errorString = "";
1773 char str[1024];
1774 // Here's the first part of the message:
1775 sprintf(str, "%s() called with a non-supported "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001776 "pCreateInfo->compositeAlpha (i.e. %s). "
1777 "Supported values are:\n",
1778 fn, surfaceCompositeAlphaStr(pCreateInfo->compositeAlpha));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001779 errorString += str;
1780 for (int i = 0; i < 32; i++) {
1781 // Build up the rest of the message:
1782 if ((1 << i) & pCapabilities->supportedCompositeAlpha) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001783 const char *newStr = surfaceCompositeAlphaStr((VkCompositeAlphaFlagBitsKHR)(1 << i));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001784 sprintf(str, " %s\n", newStr);
1785 errorString += str;
1786 }
1787 }
1788 // Log the message that we've built up:
Mark Lobodzinskia4cbbcd2016-05-24 15:44:50 -06001789 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1790 reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA,
1791 LAYER_NAME, "%s", errorString.c_str());
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001792 }
David McFarlande22cfb02016-05-20 18:26:28 -03001793 // Validate pCreateInfo->imageArrayLayers against
1794 // VkSurfaceCapabilitiesKHR::maxImageArrayLayers:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001795 if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > pCapabilities->maxImageArrayLayers)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001796 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
David McFarlande22cfb02016-05-20 18:26:28 -03001797 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_LAYERS, "%s() called with a non-supported "
1798 "pCreateInfo->imageArrayLayers (i.e. %d). "
1799 "Minimum value is 1, maximum value is %d.",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001800 fn, pCreateInfo->imageArrayLayers, pCapabilities->maxImageArrayLayers);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001801 }
1802 // Validate pCreateInfo->imageUsage against
1803 // VkSurfaceCapabilitiesKHR::supportedUsageFlags:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001804 if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & pCapabilities->supportedUsageFlags)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001805 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001806 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS, "%s() called with a non-supported "
1807 "pCreateInfo->imageUsage (i.e. 0x%08x)."
1808 " Supported flag bits are 0x%08x.",
1809 fn, pCreateInfo->imageUsage, pCapabilities->supportedUsageFlags);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001810 }
1811 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001812
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001813 // Validate pCreateInfo values with the results of
1814 // vkGetPhysicalDeviceSurfaceFormatsKHR():
1815 if (!pPhysicalDevice || !pPhysicalDevice->surfaceFormatCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001816 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001817 "%s() called before calling "
1818 "vkGetPhysicalDeviceSurfaceFormatsKHR().",
1819 fn);
1820 } else if (pCreateInfo) {
1821 // Validate pCreateInfo->imageFormat against
1822 // VkSurfaceFormatKHR::format:
1823 bool foundFormat = false;
1824 bool foundColorSpace = false;
1825 bool foundMatch = false;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001826 for (uint32_t i = 0; i < pPhysicalDevice->surfaceFormatCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001827 if (pCreateInfo->imageFormat == pPhysicalDevice->pSurfaceFormats[i].format) {
1828 // Validate pCreateInfo->imageColorSpace against
1829 // VkSurfaceFormatKHR::colorSpace:
1830 foundFormat = true;
1831 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1832 foundMatch = true;
1833 break;
1834 }
1835 } else {
1836 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1837 foundColorSpace = true;
1838 }
1839 }
1840 }
1841 if (!foundMatch) {
1842 if (!foundFormat) {
1843 if (!foundColorSpace) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001844 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1845 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP, "%s() called with neither a "
1846 "supported pCreateInfo->imageFormat "
1847 "(i.e. %d) nor a supported "
1848 "pCreateInfo->imageColorSpace "
1849 "(i.e. %d).",
1850 fn, pCreateInfo->imageFormat, pCreateInfo->imageColorSpace);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001851 } else {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001852 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1853 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT, "%s() called with a non-supported "
1854 "pCreateInfo->imageFormat (i.e. %d).",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001855 fn, pCreateInfo->imageFormat);
1856 }
1857 } else if (!foundColorSpace) {
1858 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001859 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE, "%s() called with a non-supported "
1860 "pCreateInfo->imageColorSpace (i.e. %d).",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001861 fn, pCreateInfo->imageColorSpace);
1862 }
1863 }
1864 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001865
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001866 // Validate pCreateInfo values with the results of
1867 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1868 if (!pPhysicalDevice || !pPhysicalDevice->presentModeCount) {
szdarkhackfb287d32016-03-12 18:41:19 +02001869 if (!pCreateInfo || (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR)) {
1870 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
1871 "%s() called before calling "
1872 "vkGetPhysicalDeviceSurfacePresentModesKHR().",
1873 fn);
1874 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001875 } else if (pCreateInfo) {
1876 // Validate pCreateInfo->presentMode against
1877 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1878 bool foundMatch = false;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001879 for (uint32_t i = 0; i < pPhysicalDevice->presentModeCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001880 if (pPhysicalDevice->pPresentModes[i] == pCreateInfo->presentMode) {
1881 foundMatch = true;
1882 break;
1883 }
1884 }
1885 if (!foundMatch) {
1886 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001887 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE, "%s() called with a non-supported "
1888 "pCreateInfo->presentMode (i.e. %s).",
1889 fn, presentModeStr(pCreateInfo->presentMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001890 }
1891 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001892
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001893 // Validate pCreateInfo->imageSharingMode and related values:
1894 if (pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001895 if ((pCreateInfo->queueFamilyIndexCount <= 1) || !pCreateInfo->pQueueFamilyIndices) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001896 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001897 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_VALUES, "%s() called with a supported "
baldurk209ccda2016-05-05 16:31:05 +02001898 "pCreateInfo->sharingMode of (i.e. %s), "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001899 "but with a bad value(s) for "
1900 "pCreateInfo->queueFamilyIndexCount or "
1901 "pCreateInfo->pQueueFamilyIndices).",
1902 fn, sharingModeStr(pCreateInfo->imageSharingMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001903 }
1904 } else if (pCreateInfo->imageSharingMode != VK_SHARING_MODE_EXCLUSIVE) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001905 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_BAD_SHARING_MODE,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001906 "%s() called with a non-supported "
1907 "pCreateInfo->imageSharingMode (i.e. %s).",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001908 fn, sharingModeStr(pCreateInfo->imageSharingMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001909 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001910
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001911 // Validate pCreateInfo->clipped:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001912 if (pCreateInfo && (pCreateInfo->clipped != VK_FALSE) && (pCreateInfo->clipped != VK_TRUE)) {
1913 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_BAD_BOOL,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001914 "%s() called with a VkBool32 value that is "
1915 "neither VK_TRUE nor VK_FALSE, but has the "
1916 "numeric value of %d.",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001917 fn, pCreateInfo->clipped);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001918 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001919
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001920 // Validate pCreateInfo->oldSwapchain:
1921 if (pCreateInfo && pCreateInfo->oldSwapchain) {
Ian Elliott77f46ca2016-05-05 14:10:49 -06001922 SwpSwapchain *pOldSwapchain = NULL;
1923 {
1924 auto it = my_data->swapchainMap.find(pCreateInfo->oldSwapchain);
1925 pOldSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1926 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001927 if (pOldSwapchain) {
1928 if (device != pOldSwapchain->pDevice->device) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001929 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1930 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE, "%s() called with a different VkDevice "
1931 "than the VkSwapchainKHR was created with.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001932 __FUNCTION__);
1933 }
1934 if (pCreateInfo->surface != pOldSwapchain->pSurface->surface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001935 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1936 SWAPCHAIN_CREATE_SWAP_DIFF_SURFACE, "%s() called with pCreateInfo->oldSwapchain "
1937 "that has a different VkSurfaceKHR than "
1938 "pCreateInfo->surface.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001939 fn);
1940 }
1941 } else {
1942 // TBD: Leave this in (not sure object_track will check this)?
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001943 skipCall |=
1944 LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pCreateInfo->oldSwapchain, "VkSwapchainKHR");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001945 }
1946 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001947
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001948 return skipCall;
1949}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001950
Chia-I Wufccbfe42016-04-28 14:01:30 +08001951VKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
1952 const VkAllocationCallbacks *pAllocator,
1953 VkSwapchainKHR *pSwapchain) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001954 VkResult result = VK_SUCCESS;
1955 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001956 std::unique_lock<std::mutex> lock(global_lock);
Dustin Graves080069b2016-04-05 13:48:15 -06001957 bool skipCall = validateCreateSwapchainKHR(device, pCreateInfo, pSwapchain);
Ian Elliott970a2bd2016-06-21 11:08:43 -06001958 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001959
Dustin Graves080069b2016-04-05 13:48:15 -06001960 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001961 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001962 result = my_data->device_dispatch_table->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001963 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001964
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001965 if (result == VK_SUCCESS) {
1966 // Remember the swapchain's handle, and link it to the device:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001967 SwpDevice *pDevice = NULL;
1968 {
1969 auto it = my_data->deviceMap.find(device);
1970 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1971 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001972
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001973 my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
1974 if (pDevice) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001975 pDevice->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001976 }
1977 my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
1978 my_data->swapchainMap[*pSwapchain].imageCount = 0;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001979 my_data->swapchainMap[*pSwapchain].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001980 // Store a pointer to the surface
1981 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001982 SwpInstance *pInstance = (pPhysicalDevice) ? pPhysicalDevice->pInstance : NULL;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001983 layer_data *my_instance_data =
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001984 ((pInstance) ? get_my_data_ptr(get_dispatch_key(pInstance->instance), layer_data_map) : NULL);
1985 SwpSurface *pSurface = ((my_data && pCreateInfo) ? &my_instance_data->surfaceMap[pCreateInfo->surface] : NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001986 my_data->swapchainMap[*pSwapchain].pSurface = pSurface;
1987 if (pSurface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001988 pSurface->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001989 }
1990 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001991 lock.unlock();
1992
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001993 return result;
1994 }
1995 return VK_ERROR_VALIDATION_FAILED_EXT;
1996}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001997
Chia-I Wufccbfe42016-04-28 14:01:30 +08001998VKAPI_ATTR void VKAPI_CALL
1999DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002000 // TODOs:
2001 //
2002 // - Implement a check for validity language that reads: All uses of
Ian Elliotta5d13a92016-04-07 09:05:45 -06002003 // presentable images acquired from pname:swapchain must: have completed
2004 // execution
Dustin Graves080069b2016-04-05 13:48:15 -06002005 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002006 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002007 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002008 SwpDevice *pDevice = NULL;
2009 {
2010 auto it = my_data->deviceMap.find(device);
2011 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2012 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07002013
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002014 // Validate that the swapchain extension was enabled:
2015 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002016 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2017 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2018 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002019 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002020
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002021 // Regardless of skipCall value, do some internal cleanup:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002022 SwpSwapchain *pSwapchain = NULL;
2023 {
2024 auto it = my_data->swapchainMap.find(swapchain);
2025 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2026 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002027 if (pSwapchain) {
2028 // Delete the SwpSwapchain associated with this swapchain:
2029 if (pSwapchain->pDevice) {
2030 pSwapchain->pDevice->swapchains.erase(swapchain);
2031 if (device != pSwapchain->pDevice->device) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002032 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002033 "%s() called with a different VkDevice than the "
2034 "VkSwapchainKHR was created with.",
2035 __FUNCTION__);
2036 }
2037 }
2038 if (pSwapchain->pSurface) {
2039 pSwapchain->pSurface->swapchains.erase(swapchain);
2040 }
2041 if (pSwapchain->imageCount) {
2042 pSwapchain->images.clear();
2043 }
2044 if ((pAllocator != NULL) != pSwapchain->usedAllocatorToCreate) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002045 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002046 "%s() called with incompatible pAllocator from when "
2047 "the object was created.",
2048 __FUNCTION__);
2049 }
2050 my_data->swapchainMap.erase(swapchain);
2051 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002052 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002053
Dustin Graves080069b2016-04-05 13:48:15 -06002054 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002055 // Call down the call chain:
2056 my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator);
2057 }
2058}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002059
Chia-I Wufccbfe42016-04-28 14:01:30 +08002060VKAPI_ATTR VkResult VKAPI_CALL
2061GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002062 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06002063 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002064 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002065 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002066 SwpDevice *pDevice = NULL;
2067 {
2068 auto it = my_data->deviceMap.find(device);
2069 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2070 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07002071
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002072 // Validate that the swapchain extension was enabled:
2073 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002074 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2075 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2076 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002077 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06002078 SwpSwapchain *pSwapchain = NULL;
2079 {
2080 auto it = my_data->swapchainMap.find(swapchain);
2081 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2082 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002083 if (!pSwapchainImageCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002084 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchainImageCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06002085 } else if (pSwapchain && pSwapchainImages) {
2086 // Compare the preliminary value of *pSwapchainImageCount with the
2087 // value this time:
2088 if (pSwapchain->imageCount == 0) {
2089 // Since we haven't recorded a preliminary value of
2090 // *pSwapchainImageCount, that likely means that the application
2091 // didn't previously call this function with a NULL value of
2092 // pSwapchainImages:
2093 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
2094 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2095 device, "pSwapchainImageCount", "pSwapchainImages");
2096 } else if (*pSwapchainImageCount > pSwapchain->imageCount) {
2097 skipCall |= LOG_ERROR_INVALID_COUNT(
2098 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2099 device, "pSwapchainImageCount", "pSwapchainImages",
2100 *pSwapchainImageCount, pSwapchain->imageCount);
2101 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002102 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002103 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002104
Dustin Graves080069b2016-04-05 13:48:15 -06002105 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002106 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002107 result = my_data->device_dispatch_table->GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002108 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002109
Ian Elliott32311832016-02-04 08:17:18 -07002110 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002111 {
2112 auto it = my_data->swapchainMap.find(swapchain);
2113 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2114 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002115 if ((result == VK_SUCCESS) && pSwapchain && !pSwapchainImages && pSwapchainImageCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002116 // Record the result of this preliminary query:
2117 pSwapchain->imageCount = *pSwapchainImageCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06002118 } else if ((result == VK_SUCCESS) && pSwapchain && pSwapchainImages &&
2119 pSwapchainImageCount && (*pSwapchainImageCount > 0)) {
2120 // Record the images and their state:
2121 pSwapchain->imageCount = *pSwapchainImageCount;
2122 for (uint32_t i = 0; i < *pSwapchainImageCount; i++) {
2123 pSwapchain->images[i].image = pSwapchainImages[i];
2124 pSwapchain->images[i].pSwapchain = pSwapchain;
2125 pSwapchain->images[i].acquiredByApp = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002126 }
2127 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002128 lock.unlock();
2129
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002130 return result;
2131 }
2132 return VK_ERROR_VALIDATION_FAILED_EXT;
2133}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002134
Chia-I Wufccbfe42016-04-28 14:01:30 +08002135VKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
2136 VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002137 // TODOs:
2138 //
2139 // - Address the timeout. Possibilities include looking at the state of the
2140 // swapchain's images, depending on the timeout value.
2141 // - Implement a check for validity language that reads: If pname:semaphore is
2142 // not sname:VK_NULL_HANDLE it must: be unsignalled
2143 // - Implement a check for validity language that reads: If pname:fence is not
2144 // sname:VK_NULL_HANDLE it must: be unsignalled and mustnot: be associated
2145 // with any other queue command that has not yet completed execution on that
2146 // queue
2147 // - Record/update the state of the swapchain, in case an error occurs
2148 // (e.g. VK_ERROR_OUT_OF_DATE_KHR).
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002149 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06002150 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002151 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002152 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002153 SwpDevice *pDevice = NULL;
2154 {
2155 auto it = my_data->deviceMap.find(device);
2156 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2157 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07002158
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002159 // Validate that the swapchain extension was enabled:
2160 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002161 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2162 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2163 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002164 }
Ian Elliottfa8f0322016-03-23 08:28:54 -06002165 if ((semaphore == VK_NULL_HANDLE) && (fence == VK_NULL_HANDLE)) {
Ian Elliott5da0c962016-03-23 11:13:09 -06002166 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_NO_SYNC_FOR_ACQUIRE,
2167 "%s() called with both the semaphore and fence parameters set to "
Jamie Madillcc4e9322016-05-04 12:20:15 -07002168 "VK_NULL_HANDLE (at least one should be used).", __FUNCTION__);
Ian Elliottfa8f0322016-03-23 08:28:54 -06002169 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06002170 SwpSwapchain *pSwapchain = NULL;
2171 {
2172 auto it = my_data->swapchainMap.find(swapchain);
2173 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2174 }
Ian Elliott5c680282016-04-06 14:29:56 -06002175 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
2176 if (pSwapchain && pPhysicalDevice && pPhysicalDevice->gotSurfaceCapabilities) {
2177 // Look to see if the application has already acquired the maximum
2178 // number of images, and this will push it past the spec-defined
2179 // limits:
2180 uint32_t minImageCount = pPhysicalDevice->surfaceCapabilities.minImageCount;
2181 uint32_t imagesAcquiredByApp = 0;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002182 for (uint32_t i = 0; i < pSwapchain->imageCount; i++) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002183 if (pSwapchain->images[i].acquiredByApp) {
Ian Elliott5c680282016-04-06 14:29:56 -06002184 imagesAcquiredByApp++;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002185 }
2186 }
Ian Elliott5c680282016-04-06 14:29:56 -06002187 if (imagesAcquiredByApp > (pSwapchain->imageCount - minImageCount)) {
2188 skipCall |= LOG_ERROR(
2189 VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
2190 swapchain, "VkSwapchainKHR",
2191 SWAPCHAIN_APP_ACQUIRES_TOO_MANY_IMAGES,
2192 "%s() called when it cannot succeed. The application has "
2193 "acquired %d image(s) that have not yet been presented. The "
2194 "maximum number of images that the application can "
2195 "simultaneously acquire from this swapchain (including this "
2196 "call to %s()) is %d. That value is derived by subtracting "
2197 "VkSurfaceCapabilitiesKHR::minImageCount (%d) from the number "
2198 "of images in the swapchain (%d) and adding 1.\n",
2199 __FUNCTION__, imagesAcquiredByApp, __FUNCTION__,
2200 (pSwapchain->imageCount - minImageCount + 1),
2201 minImageCount, pSwapchain->imageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002202 }
2203 }
2204 if (!pImageIndex) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002205 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pImageIndex");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002206 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002207 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002208
Dustin Graves080069b2016-04-05 13:48:15 -06002209 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002210 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002211 result = my_data->device_dispatch_table->AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002212 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002213
Ian Elliott32311832016-02-04 08:17:18 -07002214 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002215 {
2216 auto it = my_data->swapchainMap.find(swapchain);
2217 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2218 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002219 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) && pSwapchain) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002220 // Change the state of the image (now acquired by the application):
2221 pSwapchain->images[*pImageIndex].acquiredByApp = true;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002222 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002223 lock.unlock();
2224
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002225 return result;
2226 }
2227 return VK_ERROR_VALIDATION_FAILED_EXT;
2228}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002229
Chia-I Wufccbfe42016-04-28 14:01:30 +08002230VKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002231 // TODOs:
2232 //
2233 // - Implement a check for validity language that reads: Any given element of
2234 // sname:VkSemaphore in pname:pWaitSemaphores must: refer to a prior signal
2235 // of that sname:VkSemaphore that won't be consumed by any other wait on that
2236 // semaphore
2237 // - Record/update the state of the swapchain, in case an error occurs
2238 // (e.g. VK_ERROR_OUT_OF_DATE_KHR).
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002239 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06002240 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002241 layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002242
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002243 if (!pPresentInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002244 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002245 } else {
2246 if (pPresentInfo->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002247 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002248 "VK_STRUCTURE_TYPE_PRESENT_INFO_KHR");
2249 }
2250 if (pPresentInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002251 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002252 }
2253 if (!pPresentInfo->swapchainCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002254 skipCall |= LOG_ERROR_ZERO_VALUE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->swapchainCount");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002255 }
2256 if (!pPresentInfo->pSwapchains) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002257 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pSwapchains");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002258 }
2259 if (!pPresentInfo->pImageIndices) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002260 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pImageIndices");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002261 }
2262 // Note: pPresentInfo->pResults is allowed to be NULL
2263 }
Ian Elliott046ed2c2015-12-30 17:07:17 -07002264
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002265 std::unique_lock<std::mutex> lock(global_lock);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002266 for (uint32_t i = 0; pPresentInfo && (i < pPresentInfo->swapchainCount); i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002267 uint32_t index = pPresentInfo->pImageIndices[i];
Ian Elliott77f46ca2016-05-05 14:10:49 -06002268 SwpSwapchain *pSwapchain = NULL;
2269 {
2270 auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
2271 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2272 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002273 if (pSwapchain) {
2274 if (!pSwapchain->pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002275 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, pSwapchain->pDevice, "VkDevice",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002276 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002277 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2278 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002279 }
2280 if (index >= pSwapchain->imageCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002281 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
2282 SWAPCHAIN_INDEX_TOO_LARGE, "%s() called for an index that is too "
2283 "large (i.e. %d). There are only %d "
2284 "images in this VkSwapchainKHR.\n",
2285 __FUNCTION__, index, pSwapchain->imageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002286 } else {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002287 if (!pSwapchain->images[index].acquiredByApp) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002288 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i],
2289 "VkSwapchainKHR", SWAPCHAIN_INDEX_NOT_IN_USE, "%s() returned an index (i.e. %d) "
Ian Elliotta5d13a92016-04-07 09:05:45 -06002290 "for an image that is not acquired by "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002291 "the application.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002292 __FUNCTION__, index);
2293 }
2294 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06002295 SwpQueue *pQueue = NULL;
2296 {
2297 auto it = my_data->queueMap.find(queue);
2298 pQueue = (it == my_data->queueMap.end()) ? NULL : &it->second;
2299 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002300 SwpSurface *pSurface = pSwapchain->pSurface;
2301 if (pQueue && pSurface && pSurface->numQueueFamilyIndexSupport) {
2302 uint32_t queueFamilyIndex = pQueue->queueFamilyIndex;
2303 // Note: the 1st test is to ensure queueFamilyIndex is in range,
2304 // and the 2nd test is the validation check:
2305 if ((pSurface->numQueueFamilyIndexSupport > queueFamilyIndex) &&
2306 (!pSurface->pQueueFamilyIndexSupport[queueFamilyIndex])) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002307 skipCall |=
2308 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
2309 SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, "%s() called with a swapchain whose "
2310 "surface is not supported for "
2311 "presention on this device with the "
2312 "queueFamilyIndex (i.e. %d) of the "
2313 "given queue.",
2314 __FUNCTION__, queueFamilyIndex);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002315 }
2316 }
2317 }
2318 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002319 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002320
Dustin Graves080069b2016-04-05 13:48:15 -06002321 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002322 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002323 result = my_data->device_dispatch_table->QueuePresentKHR(queue, pPresentInfo);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002324 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002325
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002326 if (pPresentInfo && ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR))) {
2327 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002328 int index = pPresentInfo->pImageIndices[i];
Ian Elliott77f46ca2016-05-05 14:10:49 -06002329 SwpSwapchain *pSwapchain = NULL;
2330 {
2331 auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
2332 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2333 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002334 if (pSwapchain) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002335 // Change the state of the image (no longer acquired by the
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002336 // application):
Ian Elliotta5d13a92016-04-07 09:05:45 -06002337 pSwapchain->images[index].acquiredByApp = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002338 }
2339 }
2340 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002341 lock.unlock();
2342
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002343 return result;
2344 }
2345 return VK_ERROR_VALIDATION_FAILED_EXT;
2346}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002347
Chia-I Wufccbfe42016-04-28 14:01:30 +08002348VKAPI_ATTR void VKAPI_CALL
2349GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
Dustin Graves080069b2016-04-05 13:48:15 -06002350 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002351 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliottc4db6952016-01-21 14:29:45 -07002352
Dustin Graves080069b2016-04-05 13:48:15 -06002353 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002354 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002355 my_data->device_dispatch_table->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
Ian Elliottc4db6952016-01-21 14:29:45 -07002356
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002357 // Remember the queue's handle, and link it to the device:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002358 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002359 SwpDevice *pDevice = NULL;
2360 {
2361 auto it = my_data->deviceMap.find(device);
2362 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2363 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002364 my_data->queueMap[&pQueue].queue = *pQueue;
2365 if (pDevice) {
2366 pDevice->queues[*pQueue] = &my_data->queueMap[*pQueue];
2367 }
2368 my_data->queueMap[&pQueue].pDevice = pDevice;
2369 my_data->queueMap[&pQueue].queueFamilyIndex = queueFamilyIndex;
2370 }
2371}
Ian Elliottc4db6952016-01-21 14:29:45 -07002372
Chia-I Wufccbfe42016-04-28 14:01:30 +08002373VKAPI_ATTR VkResult VKAPI_CALL
2374CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2375 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002376 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002377 VkResult result =
2378 my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002379 if (VK_SUCCESS == result) {
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002380 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -06002381 result = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002382 }
2383 return result;
2384}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002385
Chia-I Wufccbfe42016-04-28 14:01:30 +08002386VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance,
2387 VkDebugReportCallbackEXT msgCallback,
2388 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002389 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2390 my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002391 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002392 layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
2393}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002394
Chia-I Wufccbfe42016-04-28 14:01:30 +08002395VKAPI_ATTR void VKAPI_CALL
2396DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
2397 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002398 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002399 my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix,
2400 pMsg);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002401}
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07002402
Chia-I Wub02600c2016-05-20 07:11:22 +08002403VKAPI_ATTR VkResult VKAPI_CALL
2404EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
2405 return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
2406}
2407
2408VKAPI_ATTR VkResult VKAPI_CALL
2409EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
2410 return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
2411}
2412
2413VKAPI_ATTR VkResult VKAPI_CALL
2414EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
2415 if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
2416 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
2417
2418 return VK_ERROR_LAYER_NOT_PRESENT;
2419}
2420
Chia-I Wufccbfe42016-04-28 14:01:30 +08002421VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
2422 const char *pLayerName, uint32_t *pCount,
2423 VkExtensionProperties *pProperties) {
Chia-I Wu2b481252016-04-28 14:21:13 +08002424 if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
Chia-I Wu045209e2016-04-28 11:21:49 +08002425 return util_GetExtensionProperties(0, nullptr, pCount, pProperties);
Chia-I Wu2b481252016-04-28 14:21:13 +08002426
2427 assert(physicalDevice);
2428
2429 dispatch_key key = get_dispatch_key(physicalDevice);
2430 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
2431 return my_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002432}
2433
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002434static PFN_vkVoidFunction
Chia-I Wu22813c72016-04-28 14:38:57 +08002435intercept_core_instance_command(const char *name);
2436
2437static PFN_vkVoidFunction
2438intercept_khr_surface_command(const char *name, VkInstance instance);
2439
2440static PFN_vkVoidFunction
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002441intercept_core_device_command(const char *name);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002442
Chia-I Wu83245952016-05-05 16:13:19 +08002443static PFN_vkVoidFunction
2444intercept_khr_swapchain_command(const char *name, VkDevice dev);
2445
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002446VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
2447 PFN_vkVoidFunction proc = intercept_core_device_command(funcName);
2448 if (proc)
2449 return proc;
2450
2451 assert(device);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002452
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002453 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06002454
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002455 my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Courtney Goeltzenleuchter1e9e6c82016-03-19 10:38:52 -06002456 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
Chia-I Wu83245952016-05-05 16:13:19 +08002457
2458 proc = intercept_khr_swapchain_command(funcName, device);
2459 if (proc)
2460 return proc;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002461
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002462 if (pDisp->GetDeviceProcAddr == NULL)
2463 return NULL;
2464 return pDisp->GetDeviceProcAddr(device, funcName);
2465}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002466
Chia-I Wufccbfe42016-04-28 14:01:30 +08002467VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wu22813c72016-04-28 14:38:57 +08002468 PFN_vkVoidFunction proc = intercept_core_instance_command(funcName);
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002469 if (!proc)
2470 proc = intercept_core_device_command(funcName);
2471 if (!proc)
2472 proc = intercept_khr_swapchain_command(funcName, VK_NULL_HANDLE);
Chia-I Wu22813c72016-04-28 14:38:57 +08002473 if (proc)
2474 return proc;
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07002475
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002476 assert(instance);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002477
2478 layer_data *my_data;
2479 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002480 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Ian Elliott68124ac2015-10-07 16:18:35 -06002481
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002482 proc = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
2483 if (!proc)
2484 proc = intercept_khr_surface_command(funcName, instance);
Chia-I Wu22813c72016-04-28 14:38:57 +08002485 if (proc)
2486 return proc;
Ian Elliott0b4d6242015-09-22 10:51:24 -06002487
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002488 if (pTable->GetInstanceProcAddr == NULL)
2489 return NULL;
2490 return pTable->GetInstanceProcAddr(instance, funcName);
2491}
Chia-I Wu045209e2016-04-28 11:21:49 +08002492
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002493static PFN_vkVoidFunction
Chia-I Wu22813c72016-04-28 14:38:57 +08002494intercept_core_instance_command(const char *name) {
2495 static const struct {
2496 const char *name;
2497 PFN_vkVoidFunction proc;
2498 } core_instance_commands[] = {
2499 { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
2500 { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
2501 { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) },
2502 { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
2503 { "vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices) },
Chia-I Wub02600c2016-05-20 07:11:22 +08002504 { "vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties) },
2505 { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
2506 { "vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties) },
Chia-I Wu22813c72016-04-28 14:38:57 +08002507 { "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
2508 { "vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties) },
2509 };
2510
2511 for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
2512 if (!strcmp(core_instance_commands[i].name, name))
2513 return core_instance_commands[i].proc;
2514 }
2515
2516 return nullptr;
2517}
2518
2519static PFN_vkVoidFunction
2520intercept_khr_surface_command(const char *name, VkInstance instance) {
2521 static const struct {
2522 const char *name;
2523 PFN_vkVoidFunction proc;
2524 } khr_surface_commands[] = {
2525#ifdef VK_USE_PLATFORM_ANDROID_KHR
2526 { "vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateAndroidSurfaceKHR) },
2527#endif // VK_USE_PLATFORM_ANDROID_KHR
2528#ifdef VK_USE_PLATFORM_MIR_KHR
2529 { "vkCreateMirSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateMirSurfaceKHR) },
2530 { "vkGetPhysicalDeviceMirPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceMirPresentationSupportKHR) },
2531#endif // VK_USE_PLATFORM_MIR_KHR
2532#ifdef VK_USE_PLATFORM_WAYLAND_KHR
2533 { "vkCreateWaylandSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWaylandSurfaceKHR) },
2534 { "vkGetPhysicalDeviceWaylandPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWaylandPresentationSupportKHR) },
2535#endif // VK_USE_PLATFORM_WAYLAND_KHR
2536#ifdef VK_USE_PLATFORM_WIN32_KHR
2537 { "vkCreateWin32SurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWin32SurfaceKHR) },
2538 { "vkGetPhysicalDeviceWin32PresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWin32PresentationSupportKHR) },
2539#endif // VK_USE_PLATFORM_WIN32_KHR
2540#ifdef VK_USE_PLATFORM_XCB_KHR
2541 { "vkCreateXcbSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXcbSurfaceKHR) },
2542 { "vkGetPhysicalDeviceXcbPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXcbPresentationSupportKHR) },
2543#endif // VK_USE_PLATFORM_XCB_KHR
2544#ifdef VK_USE_PLATFORM_XLIB_KHR
2545 { "vkCreateXlibSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXlibSurfaceKHR) },
2546 { "vkGetPhysicalDeviceXlibPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXlibPresentationSupportKHR) },
2547#endif // VK_USE_PLATFORM_XLIB_KHR
2548 { "vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySurfaceKHR) },
2549 { "vkGetPhysicalDeviceSurfaceSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceSupportKHR) },
2550 { "vkGetPhysicalDeviceSurfaceCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceCapabilitiesKHR) },
2551 { "vkGetPhysicalDeviceSurfaceFormatsKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceFormatsKHR) },
2552 { "vkGetPhysicalDeviceSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfacePresentModesKHR) },
Petros Bantolas2b40be72016-04-15 11:02:59 +01002553 { "vkGetPhysicalDeviceDisplayPropertiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceDisplayPropertiesKHR) },
2554 { "vkGetPhysicalDeviceDisplayPlanePropertiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceDisplayPlanePropertiesKHR) },
2555 { "vkGetDisplayPlaneSupportedDisplaysKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayPlaneSupportedDisplaysKHR) },
2556 { "vkGetDisplayModePropertiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayModePropertiesKHR) },
2557 { "vkCreateDisplayModeKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDisplayModeKHR) },
2558 { "vkGetDisplayPlaneCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayPlaneCapabilitiesKHR) },
2559 { "vkCreateDisplayPlaneSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDisplayPlaneSurfaceKHR) },
Chia-I Wu22813c72016-04-28 14:38:57 +08002560 };
2561
2562 // do not check if VK_KHR_*_surface is enabled (why?)
2563
2564 for (size_t i = 0; i < ARRAY_SIZE(khr_surface_commands); i++) {
2565 if (!strcmp(khr_surface_commands[i].name, name))
2566 return khr_surface_commands[i].proc;
2567 }
2568
2569 return nullptr;
2570}
2571
2572static PFN_vkVoidFunction
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002573intercept_core_device_command(const char *name) {
2574 static const struct {
2575 const char *name;
2576 PFN_vkVoidFunction proc;
2577 } core_device_commands[] = {
2578 { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
2579 { "vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice) },
2580 { "vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue) },
2581 };
2582
2583 for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) {
2584 if (!strcmp(core_device_commands[i].name, name))
2585 return core_device_commands[i].proc;
2586 }
2587
2588 return nullptr;
2589}
2590
Chia-I Wu83245952016-05-05 16:13:19 +08002591static PFN_vkVoidFunction
2592intercept_khr_swapchain_command(const char *name, VkDevice dev) {
2593 static const struct {
2594 const char *name;
2595 PFN_vkVoidFunction proc;
2596 } khr_swapchain_commands[] = {
2597 { "vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR) },
2598 { "vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR) },
2599 { "vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR) },
2600 { "vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR) },
2601 { "vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR) },
2602 };
2603
2604 // do not check if VK_KHR_swapchain is enabled (why?)
2605
2606 for (size_t i = 0; i < ARRAY_SIZE(khr_swapchain_commands); i++) {
2607 if (!strcmp(khr_swapchain_commands[i].name, name))
2608 return khr_swapchain_commands[i].proc;
2609 }
2610
2611 return nullptr;
2612}
2613
Chia-I Wu516b5082016-04-28 11:27:46 +08002614} // namespace swapchain
2615
2616// vk_layer_logging.h expects these to be defined
2617
Chia-I Wufccbfe42016-04-28 14:01:30 +08002618VKAPI_ATTR VkResult VKAPI_CALL
Chia-I Wu516b5082016-04-28 11:27:46 +08002619vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2620 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002621 return swapchain::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Chia-I Wu516b5082016-04-28 11:27:46 +08002622}
2623
Chia-I Wufccbfe42016-04-28 14:01:30 +08002624VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance,
Chia-I Wu516b5082016-04-28 11:27:46 +08002625 VkDebugReportCallbackEXT msgCallback,
2626 const VkAllocationCallbacks *pAllocator) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002627 swapchain::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Chia-I Wu516b5082016-04-28 11:27:46 +08002628}
2629
Chia-I Wufccbfe42016-04-28 14:01:30 +08002630VKAPI_ATTR void VKAPI_CALL
Chia-I Wu516b5082016-04-28 11:27:46 +08002631vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
2632 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002633 swapchain::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
Chia-I Wu516b5082016-04-28 11:27:46 +08002634}
2635
Chia-I Wub02600c2016-05-20 07:11:22 +08002636// loader-layer interface v0, just wrappers since there is only a layer
Chia-I Wu516b5082016-04-28 11:27:46 +08002637
Chia-I Wu045209e2016-04-28 11:21:49 +08002638VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2639vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002640 return swapchain::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002641}
2642
2643VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2644vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002645 return swapchain::EnumerateInstanceLayerProperties(pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002646}
2647
2648VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2649vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002650 // the layer command handles VK_NULL_HANDLE just fine internally
2651 assert(physicalDevice == VK_NULL_HANDLE);
2652 return swapchain::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
Chia-I Wu516b5082016-04-28 11:27:46 +08002653}
2654
2655VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
2656 const char *pLayerName, uint32_t *pCount,
2657 VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002658 // the layer command handles VK_NULL_HANDLE just fine internally
2659 assert(physicalDevice == VK_NULL_HANDLE);
Chia-I Wu2b481252016-04-28 14:21:13 +08002660 return swapchain::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
Chia-I Wu516b5082016-04-28 11:27:46 +08002661}
2662
2663VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002664 return swapchain::GetDeviceProcAddr(dev, funcName);
Chia-I Wu516b5082016-04-28 11:27:46 +08002665}
2666
2667VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002668 return swapchain::GetInstanceProcAddr(instance, funcName);
Chia-I Wu045209e2016-04-28 11:21:49 +08002669}