blob: abba1313ae1d5388ad7487c82ea5d14661601bfb [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,
Ian Elliottcf3c6422016-08-05 09:08:30 -06001687 "The surface in pCreateInfo->surface, that "
1688 "was given to %s(), must be a surface that "
1689 "is supported by the device as determined "
1690 "by vkGetPhysicalDeviceSurfaceSupportKHR(). "
1691 "However, "
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001692 "vkGetPhysicalDeviceSurfaceSupportKHR() "
Ian Elliottcf3c6422016-08-05 09:08:30 -06001693 "was never called with this surface.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001694 fn);
1695 }
Ian Elliott4f147fc2016-01-20 08:52:08 -07001696
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001697 // Validate pCreateInfo->minImageCount against
1698 // VkSurfaceCapabilitiesKHR::{min|max}ImageCount:
1699 VkSurfaceCapabilitiesKHR *pCapabilities = &pPhysicalDevice->surfaceCapabilities;
1700 if ((pCreateInfo->minImageCount < pCapabilities->minImageCount) ||
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001701 ((pCapabilities->maxImageCount > 0) && (pCreateInfo->minImageCount > pCapabilities->maxImageCount))) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001702 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001703 SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT, "%s() called with pCreateInfo->minImageCount "
1704 "= %d, which is outside the bounds returned "
1705 "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. "
1706 "minImageCount = %d, maxImageCount = %d).",
1707 fn, pCreateInfo->minImageCount, pCapabilities->minImageCount, pCapabilities->maxImageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001708 }
1709 // Validate pCreateInfo->imageExtent against
1710 // VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
1711 if ((pCapabilities->currentExtent.width == -1) &&
1712 ((pCreateInfo->imageExtent.width < pCapabilities->minImageExtent.width) ||
1713 (pCreateInfo->imageExtent.width > pCapabilities->maxImageExtent.width) ||
1714 (pCreateInfo->imageExtent.height < pCapabilities->minImageExtent.height) ||
1715 (pCreateInfo->imageExtent.height > pCapabilities->maxImageExtent.height))) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001716 skipCall |= LOG_ERROR(
1717 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS,
1718 "%s() called with pCreateInfo->imageExtent = "
1719 "(%d,%d), which is outside the bounds "
1720 "returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): "
1721 "currentExtent = (%d,%d), minImageExtent = "
1722 "(%d,%d), maxImageExtent = (%d,%d).",
1723 fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, pCapabilities->currentExtent.width,
1724 pCapabilities->currentExtent.height, pCapabilities->minImageExtent.width, pCapabilities->minImageExtent.height,
1725 pCapabilities->maxImageExtent.width, pCapabilities->maxImageExtent.height);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001726 }
1727 if ((pCapabilities->currentExtent.width != -1) &&
1728 ((pCreateInfo->imageExtent.width != pCapabilities->currentExtent.width) ||
1729 (pCreateInfo->imageExtent.height != pCapabilities->currentExtent.height))) {
1730 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001731 SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN, "%s() called with pCreateInfo->imageExtent = "
1732 "(%d,%d), which is not equal to the "
1733 "currentExtent = (%d,%d) returned by "
1734 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1735 fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height,
1736 pCapabilities->currentExtent.width, pCapabilities->currentExtent.height);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001737 }
1738 // Validate pCreateInfo->preTransform has one bit set (1st two
1739 // lines of if-statement), which bit is also set in
1740 // VkSurfaceCapabilitiesKHR::supportedTransforms (3rd line of if-statement):
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001741 if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) ||
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001742 !(pCreateInfo->preTransform & pCapabilities->supportedTransforms)) {
1743 // This is an error situation; one for which we'd like to give
1744 // the developer a helpful, multi-line error message. Build it
1745 // up a little at a time, and then log it:
1746 std::string errorString = "";
1747 char str[1024];
1748 // Here's the first part of the message:
1749 sprintf(str, "%s() called with a non-supported "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001750 "pCreateInfo->preTransform (i.e. %s). "
1751 "Supported values are:\n",
1752 fn, surfaceTransformStr(pCreateInfo->preTransform));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001753 errorString += str;
1754 for (int i = 0; i < 32; i++) {
1755 // Build up the rest of the message:
1756 if ((1 << i) & pCapabilities->supportedTransforms) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001757 const char *newStr = surfaceTransformStr((VkSurfaceTransformFlagBitsKHR)(1 << i));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001758 sprintf(str, " %s\n", newStr);
1759 errorString += str;
1760 }
1761 }
1762 // Log the message that we've built up:
Mark Lobodzinskia4cbbcd2016-05-24 15:44:50 -06001763 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1764 reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM, LAYER_NAME,
1765 "%s", errorString.c_str());
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001766 }
1767 // Validate pCreateInfo->compositeAlpha has one bit set (1st two
1768 // lines of if-statement), which bit is also set in
1769 // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha (3rd line of if-statement):
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001770 if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) ||
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001771 !((pCreateInfo->compositeAlpha) & pCapabilities->supportedCompositeAlpha)) {
1772 // This is an error situation; one for which we'd like to give
1773 // the developer a helpful, multi-line error message. Build it
1774 // up a little at a time, and then log it:
1775 std::string errorString = "";
1776 char str[1024];
1777 // Here's the first part of the message:
1778 sprintf(str, "%s() called with a non-supported "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001779 "pCreateInfo->compositeAlpha (i.e. %s). "
1780 "Supported values are:\n",
1781 fn, surfaceCompositeAlphaStr(pCreateInfo->compositeAlpha));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001782 errorString += str;
1783 for (int i = 0; i < 32; i++) {
1784 // Build up the rest of the message:
1785 if ((1 << i) & pCapabilities->supportedCompositeAlpha) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001786 const char *newStr = surfaceCompositeAlphaStr((VkCompositeAlphaFlagBitsKHR)(1 << i));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001787 sprintf(str, " %s\n", newStr);
1788 errorString += str;
1789 }
1790 }
1791 // Log the message that we've built up:
Mark Lobodzinskia4cbbcd2016-05-24 15:44:50 -06001792 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1793 reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA,
1794 LAYER_NAME, "%s", errorString.c_str());
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001795 }
David McFarlande22cfb02016-05-20 18:26:28 -03001796 // Validate pCreateInfo->imageArrayLayers against
1797 // VkSurfaceCapabilitiesKHR::maxImageArrayLayers:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001798 if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > pCapabilities->maxImageArrayLayers)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001799 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
David McFarlande22cfb02016-05-20 18:26:28 -03001800 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_LAYERS, "%s() called with a non-supported "
1801 "pCreateInfo->imageArrayLayers (i.e. %d). "
1802 "Minimum value is 1, maximum value is %d.",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001803 fn, pCreateInfo->imageArrayLayers, pCapabilities->maxImageArrayLayers);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001804 }
1805 // Validate pCreateInfo->imageUsage against
1806 // VkSurfaceCapabilitiesKHR::supportedUsageFlags:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001807 if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & pCapabilities->supportedUsageFlags)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001808 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001809 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS, "%s() called with a non-supported "
1810 "pCreateInfo->imageUsage (i.e. 0x%08x)."
1811 " Supported flag bits are 0x%08x.",
1812 fn, pCreateInfo->imageUsage, pCapabilities->supportedUsageFlags);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001813 }
1814 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001815
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001816 // Validate pCreateInfo values with the results of
1817 // vkGetPhysicalDeviceSurfaceFormatsKHR():
1818 if (!pPhysicalDevice || !pPhysicalDevice->surfaceFormatCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001819 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001820 "%s() called before calling "
1821 "vkGetPhysicalDeviceSurfaceFormatsKHR().",
1822 fn);
1823 } else if (pCreateInfo) {
1824 // Validate pCreateInfo->imageFormat against
1825 // VkSurfaceFormatKHR::format:
1826 bool foundFormat = false;
1827 bool foundColorSpace = false;
1828 bool foundMatch = false;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001829 for (uint32_t i = 0; i < pPhysicalDevice->surfaceFormatCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001830 if (pCreateInfo->imageFormat == pPhysicalDevice->pSurfaceFormats[i].format) {
1831 // Validate pCreateInfo->imageColorSpace against
1832 // VkSurfaceFormatKHR::colorSpace:
1833 foundFormat = true;
1834 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1835 foundMatch = true;
1836 break;
1837 }
1838 } else {
1839 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1840 foundColorSpace = true;
1841 }
1842 }
1843 }
1844 if (!foundMatch) {
1845 if (!foundFormat) {
1846 if (!foundColorSpace) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001847 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1848 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP, "%s() called with neither a "
1849 "supported pCreateInfo->imageFormat "
1850 "(i.e. %d) nor a supported "
1851 "pCreateInfo->imageColorSpace "
1852 "(i.e. %d).",
1853 fn, pCreateInfo->imageFormat, pCreateInfo->imageColorSpace);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001854 } else {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001855 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1856 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT, "%s() called with a non-supported "
1857 "pCreateInfo->imageFormat (i.e. %d).",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001858 fn, pCreateInfo->imageFormat);
1859 }
1860 } else if (!foundColorSpace) {
1861 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001862 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE, "%s() called with a non-supported "
1863 "pCreateInfo->imageColorSpace (i.e. %d).",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001864 fn, pCreateInfo->imageColorSpace);
1865 }
1866 }
1867 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001868
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001869 // Validate pCreateInfo values with the results of
1870 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1871 if (!pPhysicalDevice || !pPhysicalDevice->presentModeCount) {
szdarkhackfb287d32016-03-12 18:41:19 +02001872 if (!pCreateInfo || (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR)) {
1873 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
1874 "%s() called before calling "
1875 "vkGetPhysicalDeviceSurfacePresentModesKHR().",
1876 fn);
1877 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001878 } else if (pCreateInfo) {
1879 // Validate pCreateInfo->presentMode against
1880 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1881 bool foundMatch = false;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001882 for (uint32_t i = 0; i < pPhysicalDevice->presentModeCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001883 if (pPhysicalDevice->pPresentModes[i] == pCreateInfo->presentMode) {
1884 foundMatch = true;
1885 break;
1886 }
1887 }
1888 if (!foundMatch) {
1889 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001890 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE, "%s() called with a non-supported "
1891 "pCreateInfo->presentMode (i.e. %s).",
1892 fn, presentModeStr(pCreateInfo->presentMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001893 }
1894 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001895
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001896 // Validate pCreateInfo->imageSharingMode and related values:
1897 if (pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001898 if ((pCreateInfo->queueFamilyIndexCount <= 1) || !pCreateInfo->pQueueFamilyIndices) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001899 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001900 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_VALUES, "%s() called with a supported "
baldurk209ccda2016-05-05 16:31:05 +02001901 "pCreateInfo->sharingMode of (i.e. %s), "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001902 "but with a bad value(s) for "
1903 "pCreateInfo->queueFamilyIndexCount or "
1904 "pCreateInfo->pQueueFamilyIndices).",
1905 fn, sharingModeStr(pCreateInfo->imageSharingMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001906 }
1907 } else if (pCreateInfo->imageSharingMode != VK_SHARING_MODE_EXCLUSIVE) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001908 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 -07001909 "%s() called with a non-supported "
1910 "pCreateInfo->imageSharingMode (i.e. %s).",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001911 fn, sharingModeStr(pCreateInfo->imageSharingMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001912 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001913
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001914 // Validate pCreateInfo->clipped:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001915 if (pCreateInfo && (pCreateInfo->clipped != VK_FALSE) && (pCreateInfo->clipped != VK_TRUE)) {
1916 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_BAD_BOOL,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001917 "%s() called with a VkBool32 value that is "
1918 "neither VK_TRUE nor VK_FALSE, but has the "
1919 "numeric value of %d.",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001920 fn, pCreateInfo->clipped);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001921 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001922
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001923 // Validate pCreateInfo->oldSwapchain:
1924 if (pCreateInfo && pCreateInfo->oldSwapchain) {
Ian Elliott77f46ca2016-05-05 14:10:49 -06001925 SwpSwapchain *pOldSwapchain = NULL;
1926 {
1927 auto it = my_data->swapchainMap.find(pCreateInfo->oldSwapchain);
1928 pOldSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1929 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001930 if (pOldSwapchain) {
1931 if (device != pOldSwapchain->pDevice->device) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001932 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1933 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE, "%s() called with a different VkDevice "
1934 "than the VkSwapchainKHR was created with.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001935 __FUNCTION__);
1936 }
1937 if (pCreateInfo->surface != pOldSwapchain->pSurface->surface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001938 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1939 SWAPCHAIN_CREATE_SWAP_DIFF_SURFACE, "%s() called with pCreateInfo->oldSwapchain "
1940 "that has a different VkSurfaceKHR than "
1941 "pCreateInfo->surface.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001942 fn);
1943 }
1944 } else {
1945 // TBD: Leave this in (not sure object_track will check this)?
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001946 skipCall |=
1947 LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pCreateInfo->oldSwapchain, "VkSwapchainKHR");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001948 }
1949 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001950
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001951 return skipCall;
1952}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001953
Chia-I Wufccbfe42016-04-28 14:01:30 +08001954VKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
1955 const VkAllocationCallbacks *pAllocator,
1956 VkSwapchainKHR *pSwapchain) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001957 VkResult result = VK_SUCCESS;
1958 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001959 std::unique_lock<std::mutex> lock(global_lock);
Dustin Graves080069b2016-04-05 13:48:15 -06001960 bool skipCall = validateCreateSwapchainKHR(device, pCreateInfo, pSwapchain);
Ian Elliott970a2bd2016-06-21 11:08:43 -06001961 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001962
Dustin Graves080069b2016-04-05 13:48:15 -06001963 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001964 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001965 result = my_data->device_dispatch_table->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001966 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001967
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001968 if (result == VK_SUCCESS) {
1969 // Remember the swapchain's handle, and link it to the device:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001970 SwpDevice *pDevice = NULL;
1971 {
1972 auto it = my_data->deviceMap.find(device);
1973 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1974 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001975
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001976 my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
1977 if (pDevice) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001978 pDevice->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001979 }
1980 my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
1981 my_data->swapchainMap[*pSwapchain].imageCount = 0;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001982 my_data->swapchainMap[*pSwapchain].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001983 // Store a pointer to the surface
1984 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001985 SwpInstance *pInstance = (pPhysicalDevice) ? pPhysicalDevice->pInstance : NULL;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001986 layer_data *my_instance_data =
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001987 ((pInstance) ? get_my_data_ptr(get_dispatch_key(pInstance->instance), layer_data_map) : NULL);
1988 SwpSurface *pSurface = ((my_data && pCreateInfo) ? &my_instance_data->surfaceMap[pCreateInfo->surface] : NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001989 my_data->swapchainMap[*pSwapchain].pSurface = pSurface;
1990 if (pSurface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001991 pSurface->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001992 }
1993 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001994 lock.unlock();
1995
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001996 return result;
1997 }
1998 return VK_ERROR_VALIDATION_FAILED_EXT;
1999}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002000
Chia-I Wufccbfe42016-04-28 14:01:30 +08002001VKAPI_ATTR void VKAPI_CALL
2002DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002003 // TODOs:
2004 //
2005 // - Implement a check for validity language that reads: All uses of
Ian Elliotta5d13a92016-04-07 09:05:45 -06002006 // presentable images acquired from pname:swapchain must: have completed
2007 // execution
Dustin Graves080069b2016-04-05 13:48:15 -06002008 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002009 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002010 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002011 SwpDevice *pDevice = NULL;
2012 {
2013 auto it = my_data->deviceMap.find(device);
2014 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2015 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07002016
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002017 // Validate that the swapchain extension was enabled:
2018 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002019 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2020 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2021 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002022 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002023
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002024 // Regardless of skipCall value, do some internal cleanup:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002025 SwpSwapchain *pSwapchain = NULL;
2026 {
2027 auto it = my_data->swapchainMap.find(swapchain);
2028 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2029 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002030 if (pSwapchain) {
2031 // Delete the SwpSwapchain associated with this swapchain:
2032 if (pSwapchain->pDevice) {
2033 pSwapchain->pDevice->swapchains.erase(swapchain);
2034 if (device != pSwapchain->pDevice->device) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002035 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002036 "%s() called with a different VkDevice than the "
2037 "VkSwapchainKHR was created with.",
2038 __FUNCTION__);
2039 }
2040 }
2041 if (pSwapchain->pSurface) {
2042 pSwapchain->pSurface->swapchains.erase(swapchain);
2043 }
2044 if (pSwapchain->imageCount) {
2045 pSwapchain->images.clear();
2046 }
2047 if ((pAllocator != NULL) != pSwapchain->usedAllocatorToCreate) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002048 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002049 "%s() called with incompatible pAllocator from when "
2050 "the object was created.",
2051 __FUNCTION__);
2052 }
2053 my_data->swapchainMap.erase(swapchain);
2054 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002055 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002056
Dustin Graves080069b2016-04-05 13:48:15 -06002057 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002058 // Call down the call chain:
2059 my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator);
2060 }
2061}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002062
Chia-I Wufccbfe42016-04-28 14:01:30 +08002063VKAPI_ATTR VkResult VKAPI_CALL
2064GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002065 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06002066 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002067 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002068 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002069 SwpDevice *pDevice = NULL;
2070 {
2071 auto it = my_data->deviceMap.find(device);
2072 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2073 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07002074
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002075 // Validate that the swapchain extension was enabled:
2076 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002077 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2078 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2079 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002080 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06002081 SwpSwapchain *pSwapchain = NULL;
2082 {
2083 auto it = my_data->swapchainMap.find(swapchain);
2084 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2085 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002086 if (!pSwapchainImageCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002087 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchainImageCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06002088 } else if (pSwapchain && pSwapchainImages) {
2089 // Compare the preliminary value of *pSwapchainImageCount with the
2090 // value this time:
2091 if (pSwapchain->imageCount == 0) {
2092 // Since we haven't recorded a preliminary value of
2093 // *pSwapchainImageCount, that likely means that the application
2094 // didn't previously call this function with a NULL value of
2095 // pSwapchainImages:
2096 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
2097 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2098 device, "pSwapchainImageCount", "pSwapchainImages");
2099 } else if (*pSwapchainImageCount > pSwapchain->imageCount) {
2100 skipCall |= LOG_ERROR_INVALID_COUNT(
2101 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2102 device, "pSwapchainImageCount", "pSwapchainImages",
2103 *pSwapchainImageCount, pSwapchain->imageCount);
2104 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002105 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002106 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002107
Dustin Graves080069b2016-04-05 13:48:15 -06002108 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002109 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002110 result = my_data->device_dispatch_table->GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002111 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002112
Ian Elliott32311832016-02-04 08:17:18 -07002113 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002114 {
2115 auto it = my_data->swapchainMap.find(swapchain);
2116 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2117 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002118 if ((result == VK_SUCCESS) && pSwapchain && !pSwapchainImages && pSwapchainImageCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002119 // Record the result of this preliminary query:
2120 pSwapchain->imageCount = *pSwapchainImageCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06002121 } else if ((result == VK_SUCCESS) && pSwapchain && pSwapchainImages &&
2122 pSwapchainImageCount && (*pSwapchainImageCount > 0)) {
2123 // Record the images and their state:
2124 pSwapchain->imageCount = *pSwapchainImageCount;
2125 for (uint32_t i = 0; i < *pSwapchainImageCount; i++) {
2126 pSwapchain->images[i].image = pSwapchainImages[i];
2127 pSwapchain->images[i].pSwapchain = pSwapchain;
2128 pSwapchain->images[i].acquiredByApp = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002129 }
2130 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002131 lock.unlock();
2132
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002133 return result;
2134 }
2135 return VK_ERROR_VALIDATION_FAILED_EXT;
2136}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002137
Chia-I Wufccbfe42016-04-28 14:01:30 +08002138VKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
2139 VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002140 // TODOs:
2141 //
2142 // - Address the timeout. Possibilities include looking at the state of the
2143 // swapchain's images, depending on the timeout value.
2144 // - Implement a check for validity language that reads: If pname:semaphore is
2145 // not sname:VK_NULL_HANDLE it must: be unsignalled
2146 // - Implement a check for validity language that reads: If pname:fence is not
2147 // sname:VK_NULL_HANDLE it must: be unsignalled and mustnot: be associated
2148 // with any other queue command that has not yet completed execution on that
2149 // queue
2150 // - Record/update the state of the swapchain, in case an error occurs
2151 // (e.g. VK_ERROR_OUT_OF_DATE_KHR).
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002152 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06002153 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002154 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002155 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002156 SwpDevice *pDevice = NULL;
2157 {
2158 auto it = my_data->deviceMap.find(device);
2159 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2160 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07002161
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002162 // Validate that the swapchain extension was enabled:
2163 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002164 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2165 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2166 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002167 }
Ian Elliottfa8f0322016-03-23 08:28:54 -06002168 if ((semaphore == VK_NULL_HANDLE) && (fence == VK_NULL_HANDLE)) {
Ian Elliott5da0c962016-03-23 11:13:09 -06002169 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_NO_SYNC_FOR_ACQUIRE,
2170 "%s() called with both the semaphore and fence parameters set to "
Jamie Madillcc4e9322016-05-04 12:20:15 -07002171 "VK_NULL_HANDLE (at least one should be used).", __FUNCTION__);
Ian Elliottfa8f0322016-03-23 08:28:54 -06002172 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06002173 SwpSwapchain *pSwapchain = NULL;
2174 {
2175 auto it = my_data->swapchainMap.find(swapchain);
2176 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2177 }
Ian Elliott5c680282016-04-06 14:29:56 -06002178 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
2179 if (pSwapchain && pPhysicalDevice && pPhysicalDevice->gotSurfaceCapabilities) {
2180 // Look to see if the application has already acquired the maximum
2181 // number of images, and this will push it past the spec-defined
2182 // limits:
2183 uint32_t minImageCount = pPhysicalDevice->surfaceCapabilities.minImageCount;
2184 uint32_t imagesAcquiredByApp = 0;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002185 for (uint32_t i = 0; i < pSwapchain->imageCount; i++) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002186 if (pSwapchain->images[i].acquiredByApp) {
Ian Elliott5c680282016-04-06 14:29:56 -06002187 imagesAcquiredByApp++;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002188 }
2189 }
Ian Elliott5c680282016-04-06 14:29:56 -06002190 if (imagesAcquiredByApp > (pSwapchain->imageCount - minImageCount)) {
2191 skipCall |= LOG_ERROR(
2192 VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
2193 swapchain, "VkSwapchainKHR",
2194 SWAPCHAIN_APP_ACQUIRES_TOO_MANY_IMAGES,
2195 "%s() called when it cannot succeed. The application has "
2196 "acquired %d image(s) that have not yet been presented. The "
2197 "maximum number of images that the application can "
2198 "simultaneously acquire from this swapchain (including this "
2199 "call to %s()) is %d. That value is derived by subtracting "
2200 "VkSurfaceCapabilitiesKHR::minImageCount (%d) from the number "
2201 "of images in the swapchain (%d) and adding 1.\n",
2202 __FUNCTION__, imagesAcquiredByApp, __FUNCTION__,
2203 (pSwapchain->imageCount - minImageCount + 1),
2204 minImageCount, pSwapchain->imageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002205 }
2206 }
2207 if (!pImageIndex) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002208 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pImageIndex");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002209 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002210 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002211
Dustin Graves080069b2016-04-05 13:48:15 -06002212 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002213 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002214 result = my_data->device_dispatch_table->AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002215 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002216
Ian Elliott32311832016-02-04 08:17:18 -07002217 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002218 {
2219 auto it = my_data->swapchainMap.find(swapchain);
2220 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2221 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002222 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) && pSwapchain) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002223 // Change the state of the image (now acquired by the application):
2224 pSwapchain->images[*pImageIndex].acquiredByApp = true;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002225 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002226 lock.unlock();
2227
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002228 return result;
2229 }
2230 return VK_ERROR_VALIDATION_FAILED_EXT;
2231}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002232
Chia-I Wufccbfe42016-04-28 14:01:30 +08002233VKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002234 // TODOs:
2235 //
2236 // - Implement a check for validity language that reads: Any given element of
2237 // sname:VkSemaphore in pname:pWaitSemaphores must: refer to a prior signal
2238 // of that sname:VkSemaphore that won't be consumed by any other wait on that
2239 // semaphore
2240 // - Record/update the state of the swapchain, in case an error occurs
2241 // (e.g. VK_ERROR_OUT_OF_DATE_KHR).
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002242 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06002243 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002244 layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002245
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002246 if (!pPresentInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002247 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002248 } else {
2249 if (pPresentInfo->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002250 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002251 "VK_STRUCTURE_TYPE_PRESENT_INFO_KHR");
2252 }
2253 if (pPresentInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002254 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002255 }
2256 if (!pPresentInfo->swapchainCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002257 skipCall |= LOG_ERROR_ZERO_VALUE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->swapchainCount");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002258 }
2259 if (!pPresentInfo->pSwapchains) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002260 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pSwapchains");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002261 }
2262 if (!pPresentInfo->pImageIndices) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002263 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pImageIndices");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002264 }
2265 // Note: pPresentInfo->pResults is allowed to be NULL
2266 }
Ian Elliott046ed2c2015-12-30 17:07:17 -07002267
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002268 std::unique_lock<std::mutex> lock(global_lock);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002269 for (uint32_t i = 0; pPresentInfo && (i < pPresentInfo->swapchainCount); i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002270 uint32_t index = pPresentInfo->pImageIndices[i];
Ian Elliott77f46ca2016-05-05 14:10:49 -06002271 SwpSwapchain *pSwapchain = NULL;
2272 {
2273 auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
2274 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2275 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002276 if (pSwapchain) {
2277 if (!pSwapchain->pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002278 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, pSwapchain->pDevice, "VkDevice",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002279 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002280 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2281 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002282 }
2283 if (index >= pSwapchain->imageCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002284 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
2285 SWAPCHAIN_INDEX_TOO_LARGE, "%s() called for an index that is too "
2286 "large (i.e. %d). There are only %d "
2287 "images in this VkSwapchainKHR.\n",
2288 __FUNCTION__, index, pSwapchain->imageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002289 } else {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002290 if (!pSwapchain->images[index].acquiredByApp) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002291 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i],
2292 "VkSwapchainKHR", SWAPCHAIN_INDEX_NOT_IN_USE, "%s() returned an index (i.e. %d) "
Ian Elliotta5d13a92016-04-07 09:05:45 -06002293 "for an image that is not acquired by "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002294 "the application.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002295 __FUNCTION__, index);
2296 }
2297 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06002298 SwpQueue *pQueue = NULL;
2299 {
2300 auto it = my_data->queueMap.find(queue);
2301 pQueue = (it == my_data->queueMap.end()) ? NULL : &it->second;
2302 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002303 SwpSurface *pSurface = pSwapchain->pSurface;
2304 if (pQueue && pSurface && pSurface->numQueueFamilyIndexSupport) {
2305 uint32_t queueFamilyIndex = pQueue->queueFamilyIndex;
2306 // Note: the 1st test is to ensure queueFamilyIndex is in range,
2307 // and the 2nd test is the validation check:
2308 if ((pSurface->numQueueFamilyIndexSupport > queueFamilyIndex) &&
2309 (!pSurface->pQueueFamilyIndexSupport[queueFamilyIndex])) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002310 skipCall |=
2311 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
2312 SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, "%s() called with a swapchain whose "
2313 "surface is not supported for "
2314 "presention on this device with the "
2315 "queueFamilyIndex (i.e. %d) of the "
2316 "given queue.",
2317 __FUNCTION__, queueFamilyIndex);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002318 }
2319 }
2320 }
2321 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002322 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002323
Dustin Graves080069b2016-04-05 13:48:15 -06002324 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002325 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002326 result = my_data->device_dispatch_table->QueuePresentKHR(queue, pPresentInfo);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002327 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002328
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002329 if (pPresentInfo && ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR))) {
2330 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002331 int index = pPresentInfo->pImageIndices[i];
Ian Elliott77f46ca2016-05-05 14:10:49 -06002332 SwpSwapchain *pSwapchain = NULL;
2333 {
2334 auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
2335 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2336 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002337 if (pSwapchain) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002338 // Change the state of the image (no longer acquired by the
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002339 // application):
Ian Elliotta5d13a92016-04-07 09:05:45 -06002340 pSwapchain->images[index].acquiredByApp = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002341 }
2342 }
2343 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002344 lock.unlock();
2345
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002346 return result;
2347 }
2348 return VK_ERROR_VALIDATION_FAILED_EXT;
2349}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002350
Chia-I Wufccbfe42016-04-28 14:01:30 +08002351VKAPI_ATTR void VKAPI_CALL
2352GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
Dustin Graves080069b2016-04-05 13:48:15 -06002353 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002354 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliottc4db6952016-01-21 14:29:45 -07002355
Dustin Graves080069b2016-04-05 13:48:15 -06002356 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002357 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002358 my_data->device_dispatch_table->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
Ian Elliottc4db6952016-01-21 14:29:45 -07002359
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002360 // Remember the queue's handle, and link it to the device:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002361 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002362 SwpDevice *pDevice = NULL;
2363 {
2364 auto it = my_data->deviceMap.find(device);
2365 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2366 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002367 my_data->queueMap[&pQueue].queue = *pQueue;
2368 if (pDevice) {
2369 pDevice->queues[*pQueue] = &my_data->queueMap[*pQueue];
2370 }
2371 my_data->queueMap[&pQueue].pDevice = pDevice;
2372 my_data->queueMap[&pQueue].queueFamilyIndex = queueFamilyIndex;
2373 }
2374}
Ian Elliottc4db6952016-01-21 14:29:45 -07002375
Chia-I Wufccbfe42016-04-28 14:01:30 +08002376VKAPI_ATTR VkResult VKAPI_CALL
2377CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2378 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002379 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002380 VkResult result =
2381 my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002382 if (VK_SUCCESS == result) {
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002383 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -06002384 result = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002385 }
2386 return result;
2387}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002388
Chia-I Wufccbfe42016-04-28 14:01:30 +08002389VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance,
2390 VkDebugReportCallbackEXT msgCallback,
2391 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002392 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2393 my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002394 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002395 layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
2396}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002397
Chia-I Wufccbfe42016-04-28 14:01:30 +08002398VKAPI_ATTR void VKAPI_CALL
2399DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
2400 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002401 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002402 my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix,
2403 pMsg);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002404}
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07002405
Chia-I Wub02600c2016-05-20 07:11:22 +08002406VKAPI_ATTR VkResult VKAPI_CALL
2407EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
2408 return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
2409}
2410
2411VKAPI_ATTR VkResult VKAPI_CALL
2412EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
2413 return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
2414}
2415
2416VKAPI_ATTR VkResult VKAPI_CALL
2417EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
2418 if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
2419 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
2420
2421 return VK_ERROR_LAYER_NOT_PRESENT;
2422}
2423
Chia-I Wufccbfe42016-04-28 14:01:30 +08002424VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
2425 const char *pLayerName, uint32_t *pCount,
2426 VkExtensionProperties *pProperties) {
Chia-I Wu2b481252016-04-28 14:21:13 +08002427 if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
Chia-I Wu045209e2016-04-28 11:21:49 +08002428 return util_GetExtensionProperties(0, nullptr, pCount, pProperties);
Chia-I Wu2b481252016-04-28 14:21:13 +08002429
2430 assert(physicalDevice);
2431
2432 dispatch_key key = get_dispatch_key(physicalDevice);
2433 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
2434 return my_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002435}
2436
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002437static PFN_vkVoidFunction
Chia-I Wu22813c72016-04-28 14:38:57 +08002438intercept_core_instance_command(const char *name);
2439
2440static PFN_vkVoidFunction
2441intercept_khr_surface_command(const char *name, VkInstance instance);
2442
2443static PFN_vkVoidFunction
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002444intercept_core_device_command(const char *name);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002445
Chia-I Wu83245952016-05-05 16:13:19 +08002446static PFN_vkVoidFunction
2447intercept_khr_swapchain_command(const char *name, VkDevice dev);
2448
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002449VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
2450 PFN_vkVoidFunction proc = intercept_core_device_command(funcName);
2451 if (proc)
2452 return proc;
2453
2454 assert(device);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002455
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002456 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06002457
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002458 my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Courtney Goeltzenleuchter1e9e6c82016-03-19 10:38:52 -06002459 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
Chia-I Wu83245952016-05-05 16:13:19 +08002460
2461 proc = intercept_khr_swapchain_command(funcName, device);
2462 if (proc)
2463 return proc;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002464
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002465 if (pDisp->GetDeviceProcAddr == NULL)
2466 return NULL;
2467 return pDisp->GetDeviceProcAddr(device, funcName);
2468}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002469
Chia-I Wufccbfe42016-04-28 14:01:30 +08002470VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wu22813c72016-04-28 14:38:57 +08002471 PFN_vkVoidFunction proc = intercept_core_instance_command(funcName);
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002472 if (!proc)
2473 proc = intercept_core_device_command(funcName);
2474 if (!proc)
2475 proc = intercept_khr_swapchain_command(funcName, VK_NULL_HANDLE);
Chia-I Wu22813c72016-04-28 14:38:57 +08002476 if (proc)
2477 return proc;
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07002478
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002479 assert(instance);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002480
2481 layer_data *my_data;
2482 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002483 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Ian Elliott68124ac2015-10-07 16:18:35 -06002484
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002485 proc = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
2486 if (!proc)
2487 proc = intercept_khr_surface_command(funcName, instance);
Chia-I Wu22813c72016-04-28 14:38:57 +08002488 if (proc)
2489 return proc;
Ian Elliott0b4d6242015-09-22 10:51:24 -06002490
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002491 if (pTable->GetInstanceProcAddr == NULL)
2492 return NULL;
2493 return pTable->GetInstanceProcAddr(instance, funcName);
2494}
Chia-I Wu045209e2016-04-28 11:21:49 +08002495
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002496static PFN_vkVoidFunction
Chia-I Wu22813c72016-04-28 14:38:57 +08002497intercept_core_instance_command(const char *name) {
2498 static const struct {
2499 const char *name;
2500 PFN_vkVoidFunction proc;
2501 } core_instance_commands[] = {
2502 { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
2503 { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
2504 { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) },
2505 { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
2506 { "vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices) },
Chia-I Wub02600c2016-05-20 07:11:22 +08002507 { "vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties) },
2508 { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
2509 { "vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties) },
Chia-I Wu22813c72016-04-28 14:38:57 +08002510 { "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
2511 { "vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties) },
2512 };
2513
2514 for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
2515 if (!strcmp(core_instance_commands[i].name, name))
2516 return core_instance_commands[i].proc;
2517 }
2518
2519 return nullptr;
2520}
2521
2522static PFN_vkVoidFunction
2523intercept_khr_surface_command(const char *name, VkInstance instance) {
2524 static const struct {
2525 const char *name;
2526 PFN_vkVoidFunction proc;
2527 } khr_surface_commands[] = {
2528#ifdef VK_USE_PLATFORM_ANDROID_KHR
2529 { "vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateAndroidSurfaceKHR) },
2530#endif // VK_USE_PLATFORM_ANDROID_KHR
2531#ifdef VK_USE_PLATFORM_MIR_KHR
2532 { "vkCreateMirSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateMirSurfaceKHR) },
2533 { "vkGetPhysicalDeviceMirPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceMirPresentationSupportKHR) },
2534#endif // VK_USE_PLATFORM_MIR_KHR
2535#ifdef VK_USE_PLATFORM_WAYLAND_KHR
2536 { "vkCreateWaylandSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWaylandSurfaceKHR) },
2537 { "vkGetPhysicalDeviceWaylandPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWaylandPresentationSupportKHR) },
2538#endif // VK_USE_PLATFORM_WAYLAND_KHR
2539#ifdef VK_USE_PLATFORM_WIN32_KHR
2540 { "vkCreateWin32SurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWin32SurfaceKHR) },
2541 { "vkGetPhysicalDeviceWin32PresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWin32PresentationSupportKHR) },
2542#endif // VK_USE_PLATFORM_WIN32_KHR
2543#ifdef VK_USE_PLATFORM_XCB_KHR
2544 { "vkCreateXcbSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXcbSurfaceKHR) },
2545 { "vkGetPhysicalDeviceXcbPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXcbPresentationSupportKHR) },
2546#endif // VK_USE_PLATFORM_XCB_KHR
2547#ifdef VK_USE_PLATFORM_XLIB_KHR
2548 { "vkCreateXlibSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXlibSurfaceKHR) },
2549 { "vkGetPhysicalDeviceXlibPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXlibPresentationSupportKHR) },
2550#endif // VK_USE_PLATFORM_XLIB_KHR
2551 { "vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySurfaceKHR) },
2552 { "vkGetPhysicalDeviceSurfaceSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceSupportKHR) },
2553 { "vkGetPhysicalDeviceSurfaceCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceCapabilitiesKHR) },
2554 { "vkGetPhysicalDeviceSurfaceFormatsKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceFormatsKHR) },
2555 { "vkGetPhysicalDeviceSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfacePresentModesKHR) },
Petros Bantolas2b40be72016-04-15 11:02:59 +01002556 { "vkGetPhysicalDeviceDisplayPropertiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceDisplayPropertiesKHR) },
2557 { "vkGetPhysicalDeviceDisplayPlanePropertiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceDisplayPlanePropertiesKHR) },
2558 { "vkGetDisplayPlaneSupportedDisplaysKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayPlaneSupportedDisplaysKHR) },
2559 { "vkGetDisplayModePropertiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayModePropertiesKHR) },
2560 { "vkCreateDisplayModeKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDisplayModeKHR) },
2561 { "vkGetDisplayPlaneCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayPlaneCapabilitiesKHR) },
2562 { "vkCreateDisplayPlaneSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDisplayPlaneSurfaceKHR) },
Chia-I Wu22813c72016-04-28 14:38:57 +08002563 };
2564
2565 // do not check if VK_KHR_*_surface is enabled (why?)
2566
2567 for (size_t i = 0; i < ARRAY_SIZE(khr_surface_commands); i++) {
2568 if (!strcmp(khr_surface_commands[i].name, name))
2569 return khr_surface_commands[i].proc;
2570 }
2571
2572 return nullptr;
2573}
2574
2575static PFN_vkVoidFunction
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002576intercept_core_device_command(const char *name) {
2577 static const struct {
2578 const char *name;
2579 PFN_vkVoidFunction proc;
2580 } core_device_commands[] = {
2581 { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
2582 { "vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice) },
2583 { "vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue) },
2584 };
2585
2586 for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) {
2587 if (!strcmp(core_device_commands[i].name, name))
2588 return core_device_commands[i].proc;
2589 }
2590
2591 return nullptr;
2592}
2593
Chia-I Wu83245952016-05-05 16:13:19 +08002594static PFN_vkVoidFunction
2595intercept_khr_swapchain_command(const char *name, VkDevice dev) {
2596 static const struct {
2597 const char *name;
2598 PFN_vkVoidFunction proc;
2599 } khr_swapchain_commands[] = {
2600 { "vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR) },
2601 { "vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR) },
2602 { "vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR) },
2603 { "vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR) },
2604 { "vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR) },
2605 };
2606
2607 // do not check if VK_KHR_swapchain is enabled (why?)
2608
2609 for (size_t i = 0; i < ARRAY_SIZE(khr_swapchain_commands); i++) {
2610 if (!strcmp(khr_swapchain_commands[i].name, name))
2611 return khr_swapchain_commands[i].proc;
2612 }
2613
2614 return nullptr;
2615}
2616
Chia-I Wu516b5082016-04-28 11:27:46 +08002617} // namespace swapchain
2618
2619// vk_layer_logging.h expects these to be defined
2620
Chia-I Wufccbfe42016-04-28 14:01:30 +08002621VKAPI_ATTR VkResult VKAPI_CALL
Chia-I Wu516b5082016-04-28 11:27:46 +08002622vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2623 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002624 return swapchain::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Chia-I Wu516b5082016-04-28 11:27:46 +08002625}
2626
Chia-I Wufccbfe42016-04-28 14:01:30 +08002627VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance,
Chia-I Wu516b5082016-04-28 11:27:46 +08002628 VkDebugReportCallbackEXT msgCallback,
2629 const VkAllocationCallbacks *pAllocator) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002630 swapchain::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Chia-I Wu516b5082016-04-28 11:27:46 +08002631}
2632
Chia-I Wufccbfe42016-04-28 14:01:30 +08002633VKAPI_ATTR void VKAPI_CALL
Chia-I Wu516b5082016-04-28 11:27:46 +08002634vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
2635 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002636 swapchain::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
Chia-I Wu516b5082016-04-28 11:27:46 +08002637}
2638
Chia-I Wub02600c2016-05-20 07:11:22 +08002639// loader-layer interface v0, just wrappers since there is only a layer
Chia-I Wu516b5082016-04-28 11:27:46 +08002640
Chia-I Wu045209e2016-04-28 11:21:49 +08002641VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2642vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002643 return swapchain::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002644}
2645
2646VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2647vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002648 return swapchain::EnumerateInstanceLayerProperties(pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002649}
2650
2651VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2652vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002653 // the layer command handles VK_NULL_HANDLE just fine internally
2654 assert(physicalDevice == VK_NULL_HANDLE);
2655 return swapchain::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
Chia-I Wu516b5082016-04-28 11:27:46 +08002656}
2657
2658VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
2659 const char *pLayerName, uint32_t *pCount,
2660 VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002661 // the layer command handles VK_NULL_HANDLE just fine internally
2662 assert(physicalDevice == VK_NULL_HANDLE);
Chia-I Wu2b481252016-04-28 14:21:13 +08002663 return swapchain::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
Chia-I Wu516b5082016-04-28 11:27:46 +08002664}
2665
2666VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002667 return swapchain::GetDeviceProcAddr(dev, funcName);
Chia-I Wu516b5082016-04-28 11:27:46 +08002668}
2669
2670VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002671 return swapchain::GetInstanceProcAddr(instance, funcName);
Chia-I Wu045209e2016-04-28 11:21:49 +08002672}