blob: 4271120fd44863589c6d736532aa99951e4f7573 [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
Jon Ashburn5484e0c2016-03-08 17:48:44 -070045static void createDeviceRegisterExtensions(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
Jon Ashburn5484e0c2016-03-08 17:48:44 -070051 VkLayerDispatchTable *pDisp = my_device_data->device_dispatch_table;
52 PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr;
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070053
Jon Ashburn5484e0c2016-03-08 17:48:44 -070054 pDisp->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR)gpa(device, "vkCreateSwapchainKHR");
55 pDisp->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)gpa(device, "vkDestroySwapchainKHR");
56 pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)gpa(device, "vkGetSwapchainImagesKHR");
57 pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)gpa(device, "vkAcquireNextImageKHR");
58 pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR)gpa(device, "vkQueuePresentKHR");
59 pDisp->GetDeviceQueue = (PFN_vkGetDeviceQueue)gpa(device, "vkGetDeviceQueue");
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070060
Ian Elliott77f46ca2016-05-05 14:10:49 -060061 SwpPhysicalDevice *pPhysicalDevice = NULL;
62 {
63 auto it = my_instance_data->physicalDeviceMap.find(physicalDevice);
64 pPhysicalDevice = (it == my_instance_data->physicalDeviceMap.end()) ? NULL : &it->second;
65 }
Ian Elliott0b4d6242015-09-22 10:51:24 -060066 if (pPhysicalDevice) {
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070067 my_device_data->deviceMap[device].pPhysicalDevice = pPhysicalDevice;
68 pPhysicalDevice->pDevice = &my_device_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -060069 } else {
Ian Elliott07adb112016-01-05 12:51:03 -070070 // TBD: Should we leave error in (since Swapchain really needs this
71 // link)?
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070072 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 -070073 (uint64_t)physicalDevice, __LINE__, SWAPCHAIN_INVALID_HANDLE, "Swapchain",
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070074 "vkCreateDevice() called with a non-valid VkPhysicalDevice.");
Ian Elliott0b4d6242015-09-22 10:51:24 -060075 }
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070076 my_device_data->deviceMap[device].device = device;
Ian Elliott427058f2015-12-29 16:45:49 -070077 my_device_data->deviceMap[device].swapchainExtensionEnabled = false;
Ian Elliott0b4d6242015-09-22 10:51:24 -060078
79 // Record whether the WSI device extension was enabled for this VkDevice.
80 // No need to check if the extension was advertised by
81 // vkEnumerateDeviceExtensionProperties(), since the loader handles that.
Jon Ashburnf19916e2016-01-11 13:12:43 -070082 for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070083 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
Ian Elliott0b4d6242015-09-22 10:51:24 -060084
Ian Elliott427058f2015-12-29 16:45:49 -070085 my_device_data->deviceMap[device].swapchainExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -060086 }
87 }
88}
89
Jon Ashburn5484e0c2016-03-08 17:48:44 -070090static void createInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
Ian Elliott0b4d6242015-09-22 10:51:24 -060091 uint32_t i;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070092 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -070093 VkLayerInstanceDispatchTable *pDisp = my_data->instance_dispatch_table;
Ian Elliott0b4d6242015-09-22 10:51:24 -060094 PFN_vkGetInstanceProcAddr gpa = pDisp->GetInstanceProcAddr;
Ian Elliotta983e9a2015-12-22 12:18:12 -070095#ifdef VK_USE_PLATFORM_ANDROID_KHR
Jon Ashburn5484e0c2016-03-08 17:48:44 -070096 pDisp->CreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR)gpa(instance, "vkCreateAndroidSurfaceKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -070097#endif // VK_USE_PLATFORM_ANDROID_KHR
98#ifdef VK_USE_PLATFORM_MIR_KHR
Jon Ashburn5484e0c2016-03-08 17:48:44 -070099 pDisp->CreateMirSurfaceKHR = (PFN_vkCreateMirSurfaceKHR)gpa(instance, "vkCreateMirSurfaceKHR");
100 pDisp->GetPhysicalDeviceMirPresentationSupportKHR =
101 (PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -0700102#endif // VK_USE_PLATFORM_MIR_KHR
103#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700104 pDisp->CreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR)gpa(instance, "vkCreateWaylandSurfaceKHR");
105 pDisp->GetPhysicalDeviceWaylandPresentationSupportKHR =
106 (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -0700107#endif // VK_USE_PLATFORM_WAYLAND_KHR
108#ifdef VK_USE_PLATFORM_WIN32_KHR
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700109 pDisp->CreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)gpa(instance, "vkCreateWin32SurfaceKHR");
110 pDisp->GetPhysicalDeviceWin32PresentationSupportKHR =
111 (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -0700112#endif // VK_USE_PLATFORM_WIN32_KHR
113#ifdef VK_USE_PLATFORM_XCB_KHR
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700114 pDisp->CreateXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR)gpa(instance, "vkCreateXcbSurfaceKHR");
115 pDisp->GetPhysicalDeviceXcbPresentationSupportKHR =
116 (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -0700117#endif // VK_USE_PLATFORM_XCB_KHR
118#ifdef VK_USE_PLATFORM_XLIB_KHR
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700119 pDisp->CreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR)gpa(instance, "vkCreateXlibSurfaceKHR");
120 pDisp->GetPhysicalDeviceXlibPresentationSupportKHR =
121 (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
Ian Elliotta983e9a2015-12-22 12:18:12 -0700122#endif // VK_USE_PLATFORM_XLIB_KHR
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700123 pDisp->DestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)gpa(instance, "vkDestroySurfaceKHR");
124 pDisp->GetPhysicalDeviceSurfaceSupportKHR =
125 (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceSupportKHR");
126 pDisp->GetPhysicalDeviceSurfaceCapabilitiesKHR =
127 (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
128 pDisp->GetPhysicalDeviceSurfaceFormatsKHR =
129 (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR");
130 pDisp->GetPhysicalDeviceSurfacePresentModesKHR =
131 (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)gpa(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR");
Ian Elliott0b4d6242015-09-22 10:51:24 -0600132
Ian Elliott1dcd1092015-11-17 17:29:40 -0700133 // Remember this instance, and whether the VK_KHR_surface extension
Ian Elliott0b4d6242015-09-22 10:51:24 -0600134 // was enabled for it:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600135 my_data->instanceMap[instance].instance = instance;
Ian Elliott1cb77a62015-12-29 16:44:39 -0700136 my_data->instanceMap[instance].surfaceExtensionEnabled = false;
Ian Elliott8dffaf32016-01-04 14:10:30 -0700137#ifdef VK_USE_PLATFORM_ANDROID_KHR
138 my_data->instanceMap[instance].androidSurfaceExtensionEnabled = false;
139#endif // VK_USE_PLATFORM_ANDROID_KHR
140#ifdef VK_USE_PLATFORM_MIR_KHR
141 my_data->instanceMap[instance].mirSurfaceExtensionEnabled = false;
142#endif // VK_USE_PLATFORM_MIR_KHR
143#ifdef VK_USE_PLATFORM_WAYLAND_KHR
144 my_data->instanceMap[instance].waylandSurfaceExtensionEnabled = false;
145#endif // VK_USE_PLATFORM_WAYLAND_KHR
146#ifdef VK_USE_PLATFORM_WIN32_KHR
147 my_data->instanceMap[instance].win32SurfaceExtensionEnabled = false;
148#endif // VK_USE_PLATFORM_WIN32_KHR
149#ifdef VK_USE_PLATFORM_XCB_KHR
150 my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = false;
151#endif // VK_USE_PLATFORM_XCB_KHR
152#ifdef VK_USE_PLATFORM_XLIB_KHR
153 my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = false;
154#endif // VK_USE_PLATFORM_XLIB_KHR
155
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600156 // Look for one or more debug report create info structures, and copy the
157 // callback(s) for each one found (for use by vkDestroyInstance)
158 layer_copy_tmp_callbacks(pCreateInfo->pNext, &my_data->num_tmp_callbacks, &my_data->tmp_dbg_create_infos,
159 &my_data->tmp_callbacks);
160
Ian Elliott0b4d6242015-09-22 10:51:24 -0600161 // Record whether the WSI instance extension was enabled for this
162 // VkInstance. No need to check if the extension was advertised by
163 // vkEnumerateInstanceExtensionProperties(), since the loader handles that.
Jon Ashburnf19916e2016-01-11 13:12:43 -0700164 for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700165 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600166
Ian Elliott1cb77a62015-12-29 16:44:39 -0700167 my_data->instanceMap[instance].surfaceExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600168 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700169#ifdef VK_USE_PLATFORM_ANDROID_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700170 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700171
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700172 my_data->instanceMap[instance].androidSurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800173 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700174#endif // VK_USE_PLATFORM_ANDROID_KHR
175#ifdef VK_USE_PLATFORM_MIR_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700176 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_MIR_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700177
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700178 my_data->instanceMap[instance].mirSurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800179 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700180#endif // VK_USE_PLATFORM_MIR_KHR
181#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700182 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700183
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700184 my_data->instanceMap[instance].waylandSurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800185 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700186#endif // VK_USE_PLATFORM_WAYLAND_KHR
187#ifdef VK_USE_PLATFORM_WIN32_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700188 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700189
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700190 my_data->instanceMap[instance].win32SurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800191 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700192#endif // VK_USE_PLATFORM_WIN32_KHR
193#ifdef VK_USE_PLATFORM_XCB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700194 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700195
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700196 my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800197 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700198#endif // VK_USE_PLATFORM_XCB_KHR
199#ifdef VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700200 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700201
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700202 my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = true;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700203 }
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800204#endif // VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700205 }
206}
207
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700208#include "vk_dispatch_table_helper.h"
Mark Lobodzinski1079e1b2016-03-15 14:21:59 -0600209static void init_swapchain(layer_data *my_data, const VkAllocationCallbacks *pAllocator) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600210
Mark Lobodzinski1079e1b2016-03-15 14:21:59 -0600211 layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_swapchain");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700212}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600213
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700214static const char *surfaceTransformStr(VkSurfaceTransformFlagBitsKHR value) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700215 // Return a string corresponding to the value:
216 return string_VkSurfaceTransformFlagBitsKHR(value);
217}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600218
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700219static const char *surfaceCompositeAlphaStr(VkCompositeAlphaFlagBitsKHR value) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700220 // Return a string corresponding to the value:
221 return string_VkCompositeAlphaFlagBitsKHR(value);
222}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600223
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700224static const char *presentModeStr(VkPresentModeKHR value) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700225 // Return a string corresponding to the value:
226 return string_VkPresentModeKHR(value);
227}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600228
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700229static const char *sharingModeStr(VkSharingMode value) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700230 // Return a string corresponding to the value:
231 return string_VkSharingMode(value);
232}
Ian Elliott07adb112016-01-05 12:51:03 -0700233
Chia-I Wufccbfe42016-04-28 14:01:30 +0800234VKAPI_ATTR VkResult VKAPI_CALL
235CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700236 VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600237
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700238 assert(chain_info->u.pLayerInfo);
239 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700240 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700241 if (fpCreateInstance == NULL) {
242 return VK_ERROR_INITIALIZATION_FAILED;
243 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700244
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700245 // Advance the link info for the next element on the chain
246 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700247
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700248 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
249 if (result != VK_SUCCESS) {
250 return result;
251 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700252
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700253 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
Chia-I Wua6737532016-04-28 16:04:15 +0800254 my_data->instance = *pInstance;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700255 my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
256 layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700257
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700258 my_data->report_data = debug_report_create_instance(my_data->instance_dispatch_table, *pInstance,
259 pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700260
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700261 // Call the following function after my_data is initialized:
262 createInstanceRegisterExtensions(pCreateInfo, *pInstance);
Mark Lobodzinski1079e1b2016-03-15 14:21:59 -0600263 init_swapchain(my_data, pAllocator);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700264
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700265 return result;
266}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700267
Chia-I Wufccbfe42016-04-28 14:01:30 +0800268VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700269 dispatch_key key = get_dispatch_key(instance);
270 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600271 SwpInstance *pInstance = NULL;
272 {
273 auto it = my_data->instanceMap.find(instance);
274 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
275 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700276
Ian Elliott32311832016-02-04 08:17:18 -0700277 // Call down the call chain:
278 my_data->instance_dispatch_table->DestroyInstance(instance, pAllocator);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700279
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600280 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott32311832016-02-04 08:17:18 -0700281
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600282 // Enable the temporary callback(s) here to catch cleanup issues:
283 bool callback_setup = false;
284 if (my_data->num_tmp_callbacks > 0) {
285 if (!layer_enable_tmp_callbacks(my_data->report_data, my_data->num_tmp_callbacks, my_data->tmp_dbg_create_infos,
286 my_data->tmp_callbacks)) {
287 callback_setup = true;
288 }
289 }
290
Ian Elliott32311832016-02-04 08:17:18 -0700291 // Do additional internal cleanup:
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700292 if (pInstance) {
293 // Delete all of the SwpPhysicalDevice's, SwpSurface's, and the
294 // SwpInstance associated with this instance:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700295 for (auto it = pInstance->physicalDevices.begin(); it != pInstance->physicalDevices.end(); it++) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700296
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700297 // Free memory that was allocated for/by this SwpPhysicalDevice:
298 SwpPhysicalDevice *pPhysicalDevice = it->second;
299 if (pPhysicalDevice) {
Ian Elliott458696a2016-02-04 06:11:17 -0700300 if (pPhysicalDevice->pDevice) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700301 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Ian Elliott458696a2016-02-04 06:11:17 -0700302 "%s() called before all of its associated "
303 "VkDevices were destroyed.",
304 __FUNCTION__);
305 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700306 free(pPhysicalDevice->pSurfaceFormats);
307 free(pPhysicalDevice->pPresentModes);
308 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700309
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700310 // Erase the SwpPhysicalDevice's from the my_data->physicalDeviceMap (which
311 // are simply pointed to by the SwpInstance):
312 my_data->physicalDeviceMap.erase(it->second->physicalDevice);
313 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700314 for (auto it = pInstance->surfaces.begin(); it != pInstance->surfaces.end(); it++) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700315
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700316 // Free memory that was allocated for/by this SwpPhysicalDevice:
317 SwpSurface *pSurface = it->second;
318 if (pSurface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700319 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700320 "%s() called before all of its associated "
321 "VkSurfaceKHRs were destroyed.",
322 __FUNCTION__);
323 }
324 }
325 my_data->instanceMap.erase(instance);
326 }
Mark Lobodzinski3c99d552016-02-04 13:50:23 -0700327
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600328 // Disable and cleanup the temporary callback(s):
329 if (callback_setup) {
330 layer_disable_tmp_callbacks(my_data->report_data, my_data->num_tmp_callbacks, my_data->tmp_callbacks);
331 }
332 if (my_data->num_tmp_callbacks > 0) {
333 layer_free_tmp_callbacks(my_data->tmp_dbg_create_infos, my_data->tmp_callbacks);
334 my_data->num_tmp_callbacks = 0;
335 }
336
Mark Lobodzinski3c99d552016-02-04 13:50:23 -0700337 // Clean up logging callback, if any
338 while (my_data->logging_callback.size() > 0) {
339 VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
340 layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
341 my_data->logging_callback.pop_back();
342 }
343 layer_debug_report_destroy_instance(my_data->report_data);
344
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700345 delete my_data->instance_dispatch_table;
346 layer_data_map.erase(key);
347}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700348
Chia-I Wufccbfe42016-04-28 14:01:30 +0800349VKAPI_ATTR void VKAPI_CALL
350GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount,
351 VkQueueFamilyProperties *pQueueFamilyProperties) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700352 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700353
354 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700355 my_data->instance_dispatch_table->GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount,
356 pQueueFamilyProperties);
Ian Elliott32311832016-02-04 08:17:18 -0700357
358 // Record the result of this query:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600359 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600360 SwpPhysicalDevice *pPhysicalDevice = NULL;
361 {
362 auto it = my_data->physicalDeviceMap.find(physicalDevice);
363 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
364 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700365 if (pPhysicalDevice && pQueueFamilyPropertyCount && !pQueueFamilyProperties) {
Ian Elliott32311832016-02-04 08:17:18 -0700366 pPhysicalDevice->gotQueueFamilyPropertyCount = true;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700367 pPhysicalDevice->numOfQueueFamilies = *pQueueFamilyPropertyCount;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700368 }
369}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700370
371#ifdef VK_USE_PLATFORM_ANDROID_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800372VKAPI_ATTR VkResult VKAPI_CALL
373CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo,
374 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700375 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600376 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700377 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600378 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600379 SwpInstance *pInstance = NULL;
380 {
381 auto it = my_data->instanceMap.find(instance);
382 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
383 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700384
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700385 // Validate that the platform extension was enabled:
Cody Northropd08141b2016-02-01 09:52:07 -0700386 if (pInstance && !pInstance->androidSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700387 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
388 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
389 VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700390 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700391
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700392 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700393 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700394 } else {
395 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700396 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700397 "VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR");
398 }
399 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700400 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700401 }
402 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600403 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700404
Dustin Graves080069b2016-04-05 13:48:15 -0600405 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700406 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700407 result = my_data->instance_dispatch_table->CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600408 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700409
Ian Elliott32311832016-02-04 08:17:18 -0700410 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600411 {
412 auto it = my_data->instanceMap.find(instance);
413 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
414 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700415 if ((result == VK_SUCCESS) && pInstance && pSurface) {
416 // Record the VkSurfaceKHR returned by the ICD:
417 my_data->surfaceMap[*pSurface].surface = *pSurface;
418 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700419 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700420 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
421 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
422 // Point to the associated SwpInstance:
423 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
424 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600425 lock.unlock();
426
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700427 return result;
428 }
429 return VK_ERROR_VALIDATION_FAILED_EXT;
430}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700431#endif // VK_USE_PLATFORM_ANDROID_KHR
432
433#ifdef VK_USE_PLATFORM_MIR_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800434VKAPI_ATTR VkResult VKAPI_CALL
435CreateMirSurfaceKHR(VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
436 VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700437 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600438 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700439 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600440 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600441 SwpInstance *pInstance = NULL;
442 {
443 auto it = my_data->instanceMap.find(instance);
444 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
445 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700446
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700447 // Validate that the platform extension was enabled:
448 if (pInstance && !pInstance->mirSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700449 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
450 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
451 VK_KHR_MIR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700452 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700453
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700454 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700455 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700456 } else {
457 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700458 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700459 "VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR");
460 }
461 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700462 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700463 }
464 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600465 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700466
Dustin Graves080069b2016-04-05 13:48:15 -0600467 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700468 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700469 result = my_data->instance_dispatch_table->CreateMirSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600470 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700471
Ian Elliott32311832016-02-04 08:17:18 -0700472 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600473 {
474 auto it = my_data->instanceMap.find(instance);
475 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
476 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700477 if ((result == VK_SUCCESS) && pInstance && pSurface) {
478 // Record the VkSurfaceKHR returned by the ICD:
479 my_data->surfaceMap[*pSurface].surface = *pSurface;
480 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700481 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700482 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
483 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
484 // Point to the associated SwpInstance:
485 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
486 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600487 lock.unlock();
488
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700489 return result;
490 }
491 return VK_ERROR_VALIDATION_FAILED_EXT;
492}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700493
Chia-I Wufccbfe42016-04-28 14:01:30 +0800494VKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceMirPresentationSupportKHR(VkPhysicalDevice physicalDevice,
495 uint32_t queueFamilyIndex,
496 MirConnection *connection) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700497 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600498 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700499 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600500 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600501 SwpPhysicalDevice *pPhysicalDevice = NULL;
502 {
503 auto it = my_data->physicalDeviceMap.find(physicalDevice);
504 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
505 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700506
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700507 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700508 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->mirSurfaceExtensionEnabled) {
509 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700510 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700511 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
512 VK_KHR_MIR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700513 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700514 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
515 skipCall |=
516 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
517 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700518 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600519 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700520
Dustin Graves080069b2016-04-05 13:48:15 -0600521 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700522 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700523 result = my_data->instance_dispatch_table->GetPhysicalDeviceMirPresentationSupportKHR(physicalDevice, queueFamilyIndex,
524 connection);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700525 }
526 return result;
527}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700528#endif // VK_USE_PLATFORM_MIR_KHR
529
530#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800531VKAPI_ATTR VkResult VKAPI_CALL
532CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
533 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700534 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600535 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700536 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600537 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600538 SwpInstance *pInstance = NULL;
539 {
540 auto it = my_data->instanceMap.find(instance);
541 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
542 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700543
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700544 // Validate that the platform extension was enabled:
545 if (pInstance && !pInstance->waylandSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700546 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
547 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
548 VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700549 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700550
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700551 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700552 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700553 } else {
554 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700555 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700556 "VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR");
557 }
558 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700559 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700560 }
561 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600562 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700563
Dustin Graves080069b2016-04-05 13:48:15 -0600564 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700565 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700566 result = my_data->instance_dispatch_table->CreateWaylandSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600567 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700568
Ian Elliott32311832016-02-04 08:17:18 -0700569 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600570 {
571 auto it = my_data->instanceMap.find(instance);
572 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
573 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700574 if ((result == VK_SUCCESS) && pInstance && pSurface) {
575 // Record the VkSurfaceKHR returned by the ICD:
576 my_data->surfaceMap[*pSurface].surface = *pSurface;
577 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700578 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700579 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
580 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
581 // Point to the associated SwpInstance:
582 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
583 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600584 lock.unlock();
585
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700586 return result;
587 }
588 return VK_ERROR_VALIDATION_FAILED_EXT;
589}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700590
Chia-I Wufccbfe42016-04-28 14:01:30 +0800591VKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,
592 uint32_t queueFamilyIndex,
593 struct wl_display *display) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700594 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600595 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700596 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600597 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600598 SwpPhysicalDevice *pPhysicalDevice = NULL;
599 {
600 auto it = my_data->physicalDeviceMap.find(physicalDevice);
601 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
602 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700603
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700604 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700605 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->waylandSurfaceExtensionEnabled) {
606 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700607 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700608 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
609 VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700610 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700611 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
612 skipCall |=
613 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
614 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700615 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600616 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700617
Dustin Graves080069b2016-04-05 13:48:15 -0600618 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700619 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700620 result = my_data->instance_dispatch_table->GetPhysicalDeviceWaylandPresentationSupportKHR(physicalDevice, queueFamilyIndex,
621 display);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700622 }
623 return result;
624}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700625#endif // VK_USE_PLATFORM_WAYLAND_KHR
626
627#ifdef VK_USE_PLATFORM_WIN32_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800628VKAPI_ATTR VkResult VKAPI_CALL
629CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
630 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700631 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600632 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700633 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600634 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600635 SwpInstance *pInstance = NULL;
636 {
637 auto it = my_data->instanceMap.find(instance);
638 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
639 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700640
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700641 // Validate that the platform extension was enabled:
642 if (pInstance && !pInstance->win32SurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700643 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
644 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
645 VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700646 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700647
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700648 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700649 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700650 } else {
651 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700652 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700653 "VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR");
654 }
655 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700656 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700657 }
658 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600659 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700660
Dustin Graves080069b2016-04-05 13:48:15 -0600661 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700662 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700663 result = my_data->instance_dispatch_table->CreateWin32SurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600664 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700665
Ian Elliott32311832016-02-04 08:17:18 -0700666 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600667 {
668 auto it = my_data->instanceMap.find(instance);
669 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
670 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700671 if ((result == VK_SUCCESS) && pInstance && pSurface) {
672 // Record the VkSurfaceKHR returned by the ICD:
673 my_data->surfaceMap[*pSurface].surface = *pSurface;
674 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700675 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700676 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
677 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
678 // Point to the associated SwpInstance:
679 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
680 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600681 lock.unlock();
682
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700683 return result;
684 }
685 return VK_ERROR_VALIDATION_FAILED_EXT;
686}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700687
Chia-I Wufccbfe42016-04-28 14:01:30 +0800688VKAPI_ATTR VkBool32 VKAPI_CALL
689GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700690 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600691 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700692 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600693 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600694 SwpPhysicalDevice *pPhysicalDevice = NULL;
695 {
696 auto it = my_data->physicalDeviceMap.find(physicalDevice);
697 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
698 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700699
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700700 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700701 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->win32SurfaceExtensionEnabled) {
702 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700703 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700704 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
705 VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700706 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700707 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
708 skipCall |=
709 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
710 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700711 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600712 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700713
Dustin Graves080069b2016-04-05 13:48:15 -0600714 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700715 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700716 result = my_data->instance_dispatch_table->GetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700717 }
718 return result;
719}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700720#endif // VK_USE_PLATFORM_WIN32_KHR
721
722#ifdef VK_USE_PLATFORM_XCB_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800723VKAPI_ATTR VkResult VKAPI_CALL
724CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700725 VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700726 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600727 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700728 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600729 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600730 SwpInstance *pInstance = NULL;
731 {
732 auto it = my_data->instanceMap.find(instance);
733 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
734 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700735
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700736 // Validate that the platform extension was enabled:
737 if (pInstance && !pInstance->xcbSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700738 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
739 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
740 VK_KHR_XCB_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700741 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700742
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700743 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700744 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700745 } else {
746 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700747 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700748 "VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR");
749 }
750 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700751 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700752 }
753 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600754 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700755
Dustin Graves080069b2016-04-05 13:48:15 -0600756 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700757 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700758 result = my_data->instance_dispatch_table->CreateXcbSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600759 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700760
Ian Elliott32311832016-02-04 08:17:18 -0700761 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600762 {
763 auto it = my_data->instanceMap.find(instance);
764 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
765 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700766 if ((result == VK_SUCCESS) && pInstance && pSurface) {
767 // Record the VkSurfaceKHR returned by the ICD:
768 my_data->surfaceMap[*pSurface].surface = *pSurface;
769 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700770 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700771 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
772 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
773 // Point to the associated SwpInstance:
774 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
775 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600776 lock.unlock();
777
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700778 return result;
779 }
780 return VK_ERROR_VALIDATION_FAILED_EXT;
781}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700782
Chia-I Wufccbfe42016-04-28 14:01:30 +0800783VKAPI_ATTR VkBool32 VKAPI_CALL
784GetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex,
785 xcb_connection_t *connection, xcb_visualid_t visual_id) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700786 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600787 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700788 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600789 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600790 SwpPhysicalDevice *pPhysicalDevice = NULL;
791 {
792 auto it = my_data->physicalDeviceMap.find(physicalDevice);
793 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
794 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700795
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700796 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700797 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->xcbSurfaceExtensionEnabled) {
798 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700799 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700800 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
801 VK_KHR_XCB_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700802 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700803 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
804 skipCall |=
805 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
806 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700807 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600808 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700809
Dustin Graves080069b2016-04-05 13:48:15 -0600810 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700811 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700812 result = my_data->instance_dispatch_table->GetPhysicalDeviceXcbPresentationSupportKHR(physicalDevice, queueFamilyIndex,
813 connection, visual_id);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700814 }
815 return result;
816}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700817#endif // VK_USE_PLATFORM_XCB_KHR
818
819#ifdef VK_USE_PLATFORM_XLIB_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800820VKAPI_ATTR VkResult VKAPI_CALL
821CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
822 VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700823 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600824 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700825 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600826 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600827 SwpInstance *pInstance = NULL;
828 {
829 auto it = my_data->instanceMap.find(instance);
830 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
831 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700832
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700833 // Validate that the platform extension was enabled:
834 if (pInstance && !pInstance->xlibSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700835 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
836 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
837 VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700838 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700839
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700840 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700841 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700842 } else {
843 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700844 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700845 "VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR");
846 }
847 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700848 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700849 }
850 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600851 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700852
Dustin Graves080069b2016-04-05 13:48:15 -0600853 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700854 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700855 result = my_data->instance_dispatch_table->CreateXlibSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600856 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700857
Ian Elliott32311832016-02-04 08:17:18 -0700858 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600859 {
860 auto it = my_data->instanceMap.find(instance);
861 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
862 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700863 if ((result == VK_SUCCESS) && pInstance && pSurface) {
864 // Record the VkSurfaceKHR returned by the ICD:
865 my_data->surfaceMap[*pSurface].surface = *pSurface;
866 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700867 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700868 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
869 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
870 // Point to the associated SwpInstance:
871 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
872 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600873 lock.unlock();
874
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700875 return result;
876 }
877 return VK_ERROR_VALIDATION_FAILED_EXT;
878}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700879
Chia-I Wufccbfe42016-04-28 14:01:30 +0800880VKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
881 uint32_t queueFamilyIndex,
882 Display *dpy, VisualID visualID) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700883 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600884 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700885 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600886 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600887 SwpPhysicalDevice *pPhysicalDevice = NULL;
888 {
889 auto it = my_data->physicalDeviceMap.find(physicalDevice);
890 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
891 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700892
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700893 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700894 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->xlibSurfaceExtensionEnabled) {
895 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700896 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700897 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
898 VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700899 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700900 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
901 skipCall |=
902 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
903 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700904 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600905 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700906
Dustin Graves080069b2016-04-05 13:48:15 -0600907 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700908 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700909 result = my_data->instance_dispatch_table->GetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex,
910 dpy, visualID);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700911 }
912 return result;
913}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700914#endif // VK_USE_PLATFORM_XLIB_KHR
915
Chia-I Wufccbfe42016-04-28 14:01:30 +0800916VKAPI_ATTR void VKAPI_CALL
917DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) {
Dustin Graves080069b2016-04-05 13:48:15 -0600918 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700919 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600920 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600921 SwpSurface *pSurface = NULL;
922 {
923 auto it = my_data->surfaceMap.find(surface);
924 pSurface = (it == my_data->surfaceMap.end()) ? NULL : &it->second;
925 }
926 SwpInstance *pInstance = NULL;
927 {
928 auto it = my_data->instanceMap.find(instance);
929 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
930 }
Ian Elliottf6b8c782016-04-29 13:03:17 -0600931
932 // Validate that the platform extension was enabled:
933 if (pInstance && !pInstance->surfaceExtensionEnabled) {
934 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
935 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
936 VK_KHR_SURFACE_EXTENSION_NAME);
937 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700938
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700939 // Regardless of skipCall value, do some internal cleanup:
940 if (pSurface) {
941 // Delete the SwpSurface associated with this surface:
942 if (pSurface->pInstance) {
943 pSurface->pInstance->surfaces.erase(surface);
944 }
945 if (!pSurface->swapchains.empty()) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700946 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700947 "%s() called before all of its associated "
948 "VkSwapchainKHRs were destroyed.",
949 __FUNCTION__);
950 // Empty and then delete all SwpSwapchain's
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700951 for (auto it = pSurface->swapchains.begin(); it != pSurface->swapchains.end(); it++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700952 // Delete all SwpImage's
953 it->second->images.clear();
954 // In case the swapchain's device hasn't been destroyed yet
955 // (which isn't likely, but is possible), delete its
956 // association with this swapchain (i.e. so we can't point to
957 // this swpchain from that device, later on):
958 if (it->second->pDevice) {
959 it->second->pDevice->swapchains.clear();
960 }
961 }
962 pSurface->swapchains.clear();
963 }
964 if ((pAllocator != NULL) != pSurface->usedAllocatorToCreate) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700965 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700966 "%s() called with incompatible pAllocator from when "
967 "the object was created.",
968 __FUNCTION__);
969 }
970 my_data->surfaceMap.erase(surface);
971 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600972 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700973
Dustin Graves080069b2016-04-05 13:48:15 -0600974 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700975 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700976 my_data->instance_dispatch_table->DestroySurfaceKHR(instance, surface, pAllocator);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700977 }
978}
979
Chia-I Wufccbfe42016-04-28 14:01:30 +0800980VKAPI_ATTR VkResult VKAPI_CALL
981EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700982 VkResult result = VK_SUCCESS;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700983 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700984
985 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700986 result = my_data->instance_dispatch_table->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
Ian Elliott32311832016-02-04 08:17:18 -0700987
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600988 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600989 SwpInstance *pInstance = NULL;
990 {
991 auto it = my_data->instanceMap.find(instance);
992 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
993 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700994 if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices && (*pPhysicalDeviceCount > 0)) {
Ian Elliott32311832016-02-04 08:17:18 -0700995 // Record the VkPhysicalDevices returned by the ICD:
996 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700997 my_data->physicalDeviceMap[pPhysicalDevices[i]].physicalDevice = pPhysicalDevices[i];
Ian Elliott32311832016-02-04 08:17:18 -0700998 my_data->physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance;
999 my_data->physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL;
1000 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotQueueFamilyPropertyCount = false;
1001 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotSurfaceCapabilities = false;
1002 my_data->physicalDeviceMap[pPhysicalDevices[i]].surfaceFormatCount = 0;
1003 my_data->physicalDeviceMap[pPhysicalDevices[i]].pSurfaceFormats = NULL;
1004 my_data->physicalDeviceMap[pPhysicalDevices[i]].presentModeCount = 0;
1005 my_data->physicalDeviceMap[pPhysicalDevices[i]].pPresentModes = NULL;
1006 // Point to the associated SwpInstance:
1007 if (pInstance) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001008 pInstance->physicalDevices[pPhysicalDevices[i]] = &my_data->physicalDeviceMap[pPhysicalDevices[i]];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001009 }
1010 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001011 }
Ian Elliotta3c69bc2016-02-04 15:34:59 -07001012 return result;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001013}
1014
Chia-I Wufccbfe42016-04-28 14:01:30 +08001015VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice physicalDevice,
1016 const VkDeviceCreateInfo *pCreateInfo,
1017 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Chia-I Wua6737532016-04-28 16:04:15 +08001018 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001019 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
1020
1021 assert(chain_info->u.pLayerInfo);
1022 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
1023 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Chia-I Wua6737532016-04-28 16:04:15 +08001024 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001025 if (fpCreateDevice == NULL) {
1026 return VK_ERROR_INITIALIZATION_FAILED;
1027 }
1028
1029 // Advance the link info for the next element on the chain
1030 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
1031
1032 VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1033 if (result != VK_SUCCESS) {
1034 return result;
1035 }
1036
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001037 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001038 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
1039
1040 // Setup device dispatch table
1041 my_device_data->device_dispatch_table = new VkLayerDispatchTable;
1042 layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
1043
1044 my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
1045 createDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice);
1046
1047 return result;
1048}
1049
Chia-I Wufccbfe42016-04-28 14:01:30 +08001050VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001051 dispatch_key key = get_dispatch_key(device);
1052 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001053
1054 // Call down the call chain:
1055 my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
1056
1057 // Do some internal cleanup:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001058 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001059 SwpDevice *pDevice = NULL;
1060 {
1061 auto it = my_data->deviceMap.find(device);
1062 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1063 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001064 if (pDevice) {
1065 // Delete the SwpDevice associated with this device:
1066 if (pDevice->pPhysicalDevice) {
1067 pDevice->pPhysicalDevice->pDevice = NULL;
1068 }
1069 if (!pDevice->swapchains.empty()) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001070 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001071 "%s() called before all of its associated "
1072 "VkSwapchainKHRs were destroyed.",
1073 __FUNCTION__);
1074 // Empty and then delete all SwpSwapchain's
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001075 for (auto it = pDevice->swapchains.begin(); it != pDevice->swapchains.end(); it++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001076 // Delete all SwpImage's
1077 it->second->images.clear();
1078 // In case the swapchain's surface hasn't been destroyed yet
1079 // (which is likely) delete its association with this swapchain
1080 // (i.e. so we can't point to this swpchain from that surface,
1081 // later on):
1082 if (it->second->pSurface) {
1083 it->second->pSurface->swapchains.clear();
1084 }
1085 }
1086 pDevice->swapchains.clear();
1087 }
1088 my_data->deviceMap.erase(device);
1089 }
1090 delete my_data->device_dispatch_table;
1091 layer_data_map.erase(key);
1092}
1093
Chia-I Wufccbfe42016-04-28 14:01:30 +08001094VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
1095 uint32_t queueFamilyIndex, VkSurfaceKHR surface,
1096 VkBool32 *pSupported) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001097 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001098 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001099 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001100 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001101 SwpPhysicalDevice *pPhysicalDevice = NULL;
1102 {
1103 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1104 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1105 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001106
1107 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001108 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1109 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001110 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001111 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1112 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001113 }
1114 if (!pPhysicalDevice->gotQueueFamilyPropertyCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001115 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, "VkPhysicalDevice",
1116 SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES, "%s() called before calling the "
1117 "vkGetPhysicalDeviceQueueFamilyProperties "
1118 "function.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001119 __FUNCTION__);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001120 } else if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
1121 skipCall |=
1122 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
1123 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001124 }
1125 if (!pSupported) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001126 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSupported");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001127 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001128 lock.unlock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001129
Dustin Graves080069b2016-04-05 13:48:15 -06001130 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001131 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001132 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface,
1133 pSupported);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001134 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001135
Ian Elliott32311832016-02-04 08:17:18 -07001136 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001137 {
1138 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1139 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1140 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001141 if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
1142 // Record the result of this query:
1143 SwpInstance *pInstance = pPhysicalDevice->pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001144 SwpSurface *pSurface = (pInstance) ? pInstance->surfaces[surface] : NULL;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001145 if (pSurface) {
1146 pPhysicalDevice->supportedSurfaces[surface] = pSurface;
1147 if (!pSurface->numQueueFamilyIndexSupport) {
1148 if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001149 pSurface->pQueueFamilyIndexSupport =
1150 (VkBool32 *)malloc(pPhysicalDevice->numOfQueueFamilies * sizeof(VkBool32));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001151 if (pSurface->pQueueFamilyIndexSupport != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001152 pSurface->numQueueFamilyIndexSupport = pPhysicalDevice->numOfQueueFamilies;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001153 }
1154 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001155 }
1156 if (pSurface->numQueueFamilyIndexSupport) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001157 pSurface->pQueueFamilyIndexSupport[queueFamilyIndex] = *pSupported;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001158 }
1159 }
1160 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001161 lock.unlock();
1162
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001163 return result;
1164 }
1165 return VK_ERROR_VALIDATION_FAILED_EXT;
1166}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001167
Chia-I Wufccbfe42016-04-28 14:01:30 +08001168VKAPI_ATTR VkResult VKAPI_CALL
1169GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
1170 VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001171 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001172 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001173 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001174 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001175 SwpPhysicalDevice *pPhysicalDevice = NULL;
1176 {
1177 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1178 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1179 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001180
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001181 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001182 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1183 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001184 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001185 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1186 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001187 }
1188 if (!pSurfaceCapabilities) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001189 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceCapabilities");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001190 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001191 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001192
Dustin Graves080069b2016-04-05 13:48:15 -06001193 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001194 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001195 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface,
1196 pSurfaceCapabilities);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001197 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001198
Ian Elliott32311832016-02-04 08:17:18 -07001199 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001200 {
1201 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1202 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1203 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001204 if ((result == VK_SUCCESS) && pPhysicalDevice) {
1205 // Record the result of this query:
1206 pPhysicalDevice->gotSurfaceCapabilities = true;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001207 // FIXME: NEED TO COPY THIS DATA, BECAUSE pSurfaceCapabilities POINTS TO APP-ALLOCATED DATA
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001208 pPhysicalDevice->surfaceCapabilities = *pSurfaceCapabilities;
1209 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001210 lock.unlock();
1211
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001212 return result;
1213 }
1214 return VK_ERROR_VALIDATION_FAILED_EXT;
1215}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001216
Chia-I Wufccbfe42016-04-28 14:01:30 +08001217VKAPI_ATTR VkResult VKAPI_CALL
1218GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount,
1219 VkSurfaceFormatKHR *pSurfaceFormats) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001220 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001221 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001222 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001223 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001224 SwpPhysicalDevice *pPhysicalDevice = NULL;
1225 {
1226 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1227 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1228 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001229
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001230 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001231 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1232 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001233 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001234 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1235 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001236 }
1237 if (!pSurfaceFormatCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001238 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceFormatCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001239 } else if (pPhysicalDevice && pSurfaceFormats) {
1240 // Compare the preliminary value of *pSurfaceFormatCount with the
1241 // value this time:
1242 if (pPhysicalDevice->surfaceFormatCount == 0) {
1243 // Since we haven't recorded a preliminary value of
1244 // *pSurfaceFormatCount, that likely means that the application
1245 // didn't previously call this function with a NULL value of
1246 // pSurfaceFormats:
1247 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
1248 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1249 physicalDevice, "pSurfaceFormatCount", "pSurfaceFormats");
1250 } else if (*pSurfaceFormatCount > pPhysicalDevice->surfaceFormatCount) {
1251 skipCall |= LOG_ERROR_INVALID_COUNT(
1252 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1253 physicalDevice, "pSurfaceFormatCount", "pSurfaceFormats",
1254 *pSurfaceFormatCount, pPhysicalDevice->surfaceFormatCount);
1255 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001256 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001257 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001258
Dustin Graves080069b2016-04-05 13:48:15 -06001259 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001260 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001261 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount,
1262 pSurfaceFormats);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001263 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001264
Ian Elliott32311832016-02-04 08:17:18 -07001265 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001266 {
1267 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1268 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1269 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001270 if ((result == VK_SUCCESS) && pPhysicalDevice && !pSurfaceFormats && pSurfaceFormatCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001271 // Record the result of this preliminary query:
1272 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001273 } else if ((result == VK_SUCCESS) && pPhysicalDevice &&
1274 pSurfaceFormats && pSurfaceFormatCount &&
1275 (*pSurfaceFormatCount > 0)) {
1276 // Record the result of this query:
1277 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
1278 pPhysicalDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)malloc(*pSurfaceFormatCount * sizeof(VkSurfaceFormatKHR));
1279 if (pPhysicalDevice->pSurfaceFormats) {
1280 for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) {
1281 pPhysicalDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001282 }
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001283 } else {
1284 pPhysicalDevice->surfaceFormatCount = 0;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001285 }
1286 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001287 lock.unlock();
1288
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001289 return result;
1290 }
1291 return VK_ERROR_VALIDATION_FAILED_EXT;
1292}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001293
Chia-I Wufccbfe42016-04-28 14:01:30 +08001294VKAPI_ATTR VkResult VKAPI_CALL
1295GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pPresentModeCount,
1296 VkPresentModeKHR *pPresentModes) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001297 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001298 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001299 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001300 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001301 SwpPhysicalDevice *pPhysicalDevice = NULL;
1302 {
1303 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1304 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1305 }
Ian Elliott07adb112016-01-05 12:51:03 -07001306
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001307 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001308 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1309 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001310 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001311 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1312 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001313 }
1314 if (!pPresentModeCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001315 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pPresentModeCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001316 } else if (pPhysicalDevice && pPresentModes) {
1317 // Compare the preliminary value of *pPresentModeCount with the
1318 // value this time:
1319 if (pPhysicalDevice->presentModeCount == 0) {
1320 // Since we haven't recorded a preliminary value of
1321 // *pPresentModeCount, that likely means that the application
1322 // didn't previously call this function with a NULL value of
1323 // pPresentModes:
1324 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
1325 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1326 physicalDevice, "pPresentModeCount", "pPresentModes");
1327 } else if (*pPresentModeCount > pPhysicalDevice->presentModeCount) {
1328 skipCall |= LOG_ERROR_INVALID_COUNT(
1329 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1330 physicalDevice, "pPresentModeCount", "pPresentModes",
1331 *pPresentModeCount, pPhysicalDevice->presentModeCount);
1332 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001333 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001334 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001335
Dustin Graves080069b2016-04-05 13:48:15 -06001336 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001337 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001338 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface,
1339 pPresentModeCount, pPresentModes);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001340 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001341
Ian Elliott32311832016-02-04 08:17:18 -07001342 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001343 {
1344 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1345 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1346 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001347 if ((result == VK_SUCCESS) && pPhysicalDevice && !pPresentModes && pPresentModeCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001348 // Record the result of this preliminary query:
1349 pPhysicalDevice->presentModeCount = *pPresentModeCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001350 } else if ((result == VK_SUCCESS) && pPhysicalDevice &&
1351 pPresentModes && pPresentModeCount &&
1352 (*pPresentModeCount > 0)) {
1353 // Record the result of this query:
1354 pPhysicalDevice->presentModeCount = *pPresentModeCount;
1355 pPhysicalDevice->pPresentModes = (VkPresentModeKHR *)malloc(*pPresentModeCount * sizeof(VkPresentModeKHR));
1356 if (pPhysicalDevice->pPresentModes) {
1357 for (uint32_t i = 0; i < *pPresentModeCount; i++) {
1358 pPhysicalDevice->pPresentModes[i] = pPresentModes[i];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001359 }
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001360 } else {
1361 pPhysicalDevice->presentModeCount = 0;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001362 }
1363 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001364 lock.unlock();
1365
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001366 return result;
1367 }
1368 return VK_ERROR_VALIDATION_FAILED_EXT;
1369}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001370
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001371// This function does the up-front validation work for vkCreateSwapchainKHR(),
Dustin Graves080069b2016-04-05 13:48:15 -06001372// and returns true if a logging callback indicates that the call down the
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001373// chain should be skipped:
Dustin Graves080069b2016-04-05 13:48:15 -06001374static bool validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, VkSwapchainKHR *pSwapchain) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001375 // TODO: Validate cases of re-creating a swapchain (the current code
1376 // assumes a new swapchain is being created).
Dustin Graves080069b2016-04-05 13:48:15 -06001377 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001378 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1379 char fn[] = "vkCreateSwapchainKHR";
Ian Elliott77f46ca2016-05-05 14:10:49 -06001380 SwpDevice *pDevice = NULL;
1381 {
1382 auto it = my_data->deviceMap.find(device);
1383 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1384 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001385
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001386 // Validate that the swapchain extension was enabled:
1387 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001388 return LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1389 "%s() called even though the %s extension was not enabled for this VkDevice.", fn,
1390 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001391 }
1392 if (!pCreateInfo) {
Ian Elliott432a3172016-05-09 12:33:47 -06001393 return LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001394 } else {
1395 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001396 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001397 "VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR");
1398 }
1399 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001400 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001401 }
1402 }
1403 if (!pSwapchain) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001404 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchain");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001405 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001406
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001407 // Keep around a useful pointer to pPhysicalDevice:
1408 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001409
Mark Lobodzinskid40b2db2016-02-25 13:56:57 -07001410 // Validate pCreateInfo values with result of
1411 // vkGetPhysicalDeviceQueueFamilyProperties
1412 if (pPhysicalDevice && pPhysicalDevice->gotQueueFamilyPropertyCount) {
Michael Mc Donnell75ecdb72016-04-03 14:47:51 -07001413 for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001414 if (pCreateInfo->pQueueFamilyIndices[i] >= pPhysicalDevice->numOfQueueFamilies) {
1415 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
1416 "VkPhysicalDevice", pCreateInfo->pQueueFamilyIndices[i],
1417 pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinskid40b2db2016-02-25 13:56:57 -07001418 }
1419 }
1420 }
1421
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001422 // Validate pCreateInfo values with the results of
1423 // vkGetPhysicalDeviceSurfaceCapabilitiesKHR():
1424 if (!pPhysicalDevice || !pPhysicalDevice->gotSurfaceCapabilities) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001425 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001426 "%s() called before calling "
1427 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1428 fn);
1429 } else if (pCreateInfo) {
1430 // Validate pCreateInfo->surface to make sure that
1431 // vkGetPhysicalDeviceSurfaceSupportKHR() reported this as a supported
1432 // surface:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001433 SwpSurface *pSurface = ((pPhysicalDevice) ? pPhysicalDevice->supportedSurfaces[pCreateInfo->surface] : NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001434 if (!pSurface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001435 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001436 "%s() called with pCreateInfo->surface that "
1437 "was not returned by "
1438 "vkGetPhysicalDeviceSurfaceSupportKHR() "
1439 "for the device.",
1440 fn);
1441 }
Ian Elliott4f147fc2016-01-20 08:52:08 -07001442
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001443 // Validate pCreateInfo->minImageCount against
1444 // VkSurfaceCapabilitiesKHR::{min|max}ImageCount:
1445 VkSurfaceCapabilitiesKHR *pCapabilities = &pPhysicalDevice->surfaceCapabilities;
1446 if ((pCreateInfo->minImageCount < pCapabilities->minImageCount) ||
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001447 ((pCapabilities->maxImageCount > 0) && (pCreateInfo->minImageCount > pCapabilities->maxImageCount))) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001448 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001449 SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT, "%s() called with pCreateInfo->minImageCount "
1450 "= %d, which is outside the bounds returned "
1451 "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. "
1452 "minImageCount = %d, maxImageCount = %d).",
1453 fn, pCreateInfo->minImageCount, pCapabilities->minImageCount, pCapabilities->maxImageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001454 }
1455 // Validate pCreateInfo->imageExtent against
1456 // VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
1457 if ((pCapabilities->currentExtent.width == -1) &&
1458 ((pCreateInfo->imageExtent.width < pCapabilities->minImageExtent.width) ||
1459 (pCreateInfo->imageExtent.width > pCapabilities->maxImageExtent.width) ||
1460 (pCreateInfo->imageExtent.height < pCapabilities->minImageExtent.height) ||
1461 (pCreateInfo->imageExtent.height > pCapabilities->maxImageExtent.height))) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001462 skipCall |= LOG_ERROR(
1463 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS,
1464 "%s() called with pCreateInfo->imageExtent = "
1465 "(%d,%d), which is outside the bounds "
1466 "returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): "
1467 "currentExtent = (%d,%d), minImageExtent = "
1468 "(%d,%d), maxImageExtent = (%d,%d).",
1469 fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, pCapabilities->currentExtent.width,
1470 pCapabilities->currentExtent.height, pCapabilities->minImageExtent.width, pCapabilities->minImageExtent.height,
1471 pCapabilities->maxImageExtent.width, pCapabilities->maxImageExtent.height);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001472 }
1473 if ((pCapabilities->currentExtent.width != -1) &&
1474 ((pCreateInfo->imageExtent.width != pCapabilities->currentExtent.width) ||
1475 (pCreateInfo->imageExtent.height != pCapabilities->currentExtent.height))) {
1476 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001477 SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN, "%s() called with pCreateInfo->imageExtent = "
1478 "(%d,%d), which is not equal to the "
1479 "currentExtent = (%d,%d) returned by "
1480 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1481 fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height,
1482 pCapabilities->currentExtent.width, pCapabilities->currentExtent.height);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001483 }
1484 // Validate pCreateInfo->preTransform has one bit set (1st two
1485 // lines of if-statement), which bit is also set in
1486 // VkSurfaceCapabilitiesKHR::supportedTransforms (3rd line of if-statement):
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001487 if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) ||
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001488 !(pCreateInfo->preTransform & pCapabilities->supportedTransforms)) {
1489 // This is an error situation; one for which we'd like to give
1490 // the developer a helpful, multi-line error message. Build it
1491 // up a little at a time, and then log it:
1492 std::string errorString = "";
1493 char str[1024];
1494 // Here's the first part of the message:
1495 sprintf(str, "%s() called with a non-supported "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001496 "pCreateInfo->preTransform (i.e. %s). "
1497 "Supported values are:\n",
1498 fn, surfaceTransformStr(pCreateInfo->preTransform));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001499 errorString += str;
1500 for (int i = 0; i < 32; i++) {
1501 // Build up the rest of the message:
1502 if ((1 << i) & pCapabilities->supportedTransforms) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001503 const char *newStr = surfaceTransformStr((VkSurfaceTransformFlagBitsKHR)(1 << i));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001504 sprintf(str, " %s\n", newStr);
1505 errorString += str;
1506 }
1507 }
1508 // Log the message that we've built up:
Mark Lobodzinskia4cbbcd2016-05-24 15:44:50 -06001509 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1510 reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM, LAYER_NAME,
1511 "%s", errorString.c_str());
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001512 }
1513 // Validate pCreateInfo->compositeAlpha has one bit set (1st two
1514 // lines of if-statement), which bit is also set in
1515 // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha (3rd line of if-statement):
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001516 if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) ||
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001517 !((pCreateInfo->compositeAlpha) & pCapabilities->supportedCompositeAlpha)) {
1518 // This is an error situation; one for which we'd like to give
1519 // the developer a helpful, multi-line error message. Build it
1520 // up a little at a time, and then log it:
1521 std::string errorString = "";
1522 char str[1024];
1523 // Here's the first part of the message:
1524 sprintf(str, "%s() called with a non-supported "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001525 "pCreateInfo->compositeAlpha (i.e. %s). "
1526 "Supported values are:\n",
1527 fn, surfaceCompositeAlphaStr(pCreateInfo->compositeAlpha));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001528 errorString += str;
1529 for (int i = 0; i < 32; i++) {
1530 // Build up the rest of the message:
1531 if ((1 << i) & pCapabilities->supportedCompositeAlpha) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001532 const char *newStr = surfaceCompositeAlphaStr((VkCompositeAlphaFlagBitsKHR)(1 << i));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001533 sprintf(str, " %s\n", newStr);
1534 errorString += str;
1535 }
1536 }
1537 // Log the message that we've built up:
Mark Lobodzinskia4cbbcd2016-05-24 15:44:50 -06001538 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1539 reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA,
1540 LAYER_NAME, "%s", errorString.c_str());
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001541 }
David McFarlande22cfb02016-05-20 18:26:28 -03001542 // Validate pCreateInfo->imageArrayLayers against
1543 // VkSurfaceCapabilitiesKHR::maxImageArrayLayers:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001544 if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > pCapabilities->maxImageArrayLayers)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001545 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
David McFarlande22cfb02016-05-20 18:26:28 -03001546 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_LAYERS, "%s() called with a non-supported "
1547 "pCreateInfo->imageArrayLayers (i.e. %d). "
1548 "Minimum value is 1, maximum value is %d.",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001549 fn, pCreateInfo->imageArrayLayers, pCapabilities->maxImageArrayLayers);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001550 }
1551 // Validate pCreateInfo->imageUsage against
1552 // VkSurfaceCapabilitiesKHR::supportedUsageFlags:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001553 if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & pCapabilities->supportedUsageFlags)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001554 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001555 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS, "%s() called with a non-supported "
1556 "pCreateInfo->imageUsage (i.e. 0x%08x)."
1557 " Supported flag bits are 0x%08x.",
1558 fn, pCreateInfo->imageUsage, pCapabilities->supportedUsageFlags);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001559 }
1560 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001561
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001562 // Validate pCreateInfo values with the results of
1563 // vkGetPhysicalDeviceSurfaceFormatsKHR():
1564 if (!pPhysicalDevice || !pPhysicalDevice->surfaceFormatCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001565 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001566 "%s() called before calling "
1567 "vkGetPhysicalDeviceSurfaceFormatsKHR().",
1568 fn);
1569 } else if (pCreateInfo) {
1570 // Validate pCreateInfo->imageFormat against
1571 // VkSurfaceFormatKHR::format:
1572 bool foundFormat = false;
1573 bool foundColorSpace = false;
1574 bool foundMatch = false;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001575 for (uint32_t i = 0; i < pPhysicalDevice->surfaceFormatCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001576 if (pCreateInfo->imageFormat == pPhysicalDevice->pSurfaceFormats[i].format) {
1577 // Validate pCreateInfo->imageColorSpace against
1578 // VkSurfaceFormatKHR::colorSpace:
1579 foundFormat = true;
1580 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1581 foundMatch = true;
1582 break;
1583 }
1584 } else {
1585 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1586 foundColorSpace = true;
1587 }
1588 }
1589 }
1590 if (!foundMatch) {
1591 if (!foundFormat) {
1592 if (!foundColorSpace) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001593 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1594 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP, "%s() called with neither a "
1595 "supported pCreateInfo->imageFormat "
1596 "(i.e. %d) nor a supported "
1597 "pCreateInfo->imageColorSpace "
1598 "(i.e. %d).",
1599 fn, pCreateInfo->imageFormat, pCreateInfo->imageColorSpace);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001600 } else {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001601 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1602 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT, "%s() called with a non-supported "
1603 "pCreateInfo->imageFormat (i.e. %d).",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001604 fn, pCreateInfo->imageFormat);
1605 }
1606 } else if (!foundColorSpace) {
1607 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001608 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE, "%s() called with a non-supported "
1609 "pCreateInfo->imageColorSpace (i.e. %d).",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001610 fn, pCreateInfo->imageColorSpace);
1611 }
1612 }
1613 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001614
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001615 // Validate pCreateInfo values with the results of
1616 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1617 if (!pPhysicalDevice || !pPhysicalDevice->presentModeCount) {
szdarkhackfb287d32016-03-12 18:41:19 +02001618 if (!pCreateInfo || (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR)) {
1619 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
1620 "%s() called before calling "
1621 "vkGetPhysicalDeviceSurfacePresentModesKHR().",
1622 fn);
1623 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001624 } else if (pCreateInfo) {
1625 // Validate pCreateInfo->presentMode against
1626 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1627 bool foundMatch = false;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001628 for (uint32_t i = 0; i < pPhysicalDevice->presentModeCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001629 if (pPhysicalDevice->pPresentModes[i] == pCreateInfo->presentMode) {
1630 foundMatch = true;
1631 break;
1632 }
1633 }
1634 if (!foundMatch) {
1635 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001636 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE, "%s() called with a non-supported "
1637 "pCreateInfo->presentMode (i.e. %s).",
1638 fn, presentModeStr(pCreateInfo->presentMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001639 }
1640 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001641
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001642 // Validate pCreateInfo->imageSharingMode and related values:
1643 if (pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001644 if ((pCreateInfo->queueFamilyIndexCount <= 1) || !pCreateInfo->pQueueFamilyIndices) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001645 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001646 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_VALUES, "%s() called with a supported "
baldurk209ccda2016-05-05 16:31:05 +02001647 "pCreateInfo->sharingMode of (i.e. %s), "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001648 "but with a bad value(s) for "
1649 "pCreateInfo->queueFamilyIndexCount or "
1650 "pCreateInfo->pQueueFamilyIndices).",
1651 fn, sharingModeStr(pCreateInfo->imageSharingMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001652 }
1653 } else if (pCreateInfo->imageSharingMode != VK_SHARING_MODE_EXCLUSIVE) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001654 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 -07001655 "%s() called with a non-supported "
1656 "pCreateInfo->imageSharingMode (i.e. %s).",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001657 fn, sharingModeStr(pCreateInfo->imageSharingMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001658 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001659
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001660 // Validate pCreateInfo->clipped:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001661 if (pCreateInfo && (pCreateInfo->clipped != VK_FALSE) && (pCreateInfo->clipped != VK_TRUE)) {
1662 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_BAD_BOOL,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001663 "%s() called with a VkBool32 value that is "
1664 "neither VK_TRUE nor VK_FALSE, but has the "
1665 "numeric value of %d.",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001666 fn, pCreateInfo->clipped);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001667 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001668
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001669 // Validate pCreateInfo->oldSwapchain:
1670 if (pCreateInfo && pCreateInfo->oldSwapchain) {
Ian Elliott77f46ca2016-05-05 14:10:49 -06001671 SwpSwapchain *pOldSwapchain = NULL;
1672 {
1673 auto it = my_data->swapchainMap.find(pCreateInfo->oldSwapchain);
1674 pOldSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1675 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001676 if (pOldSwapchain) {
1677 if (device != pOldSwapchain->pDevice->device) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001678 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1679 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE, "%s() called with a different VkDevice "
1680 "than the VkSwapchainKHR was created with.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001681 __FUNCTION__);
1682 }
1683 if (pCreateInfo->surface != pOldSwapchain->pSurface->surface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001684 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1685 SWAPCHAIN_CREATE_SWAP_DIFF_SURFACE, "%s() called with pCreateInfo->oldSwapchain "
1686 "that has a different VkSurfaceKHR than "
1687 "pCreateInfo->surface.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001688 fn);
1689 }
1690 } else {
1691 // TBD: Leave this in (not sure object_track will check this)?
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001692 skipCall |=
1693 LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pCreateInfo->oldSwapchain, "VkSwapchainKHR");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001694 }
1695 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001696
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001697 return skipCall;
1698}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001699
Chia-I Wufccbfe42016-04-28 14:01:30 +08001700VKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
1701 const VkAllocationCallbacks *pAllocator,
1702 VkSwapchainKHR *pSwapchain) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001703 VkResult result = VK_SUCCESS;
1704 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001705 std::unique_lock<std::mutex> lock(global_lock);
Dustin Graves080069b2016-04-05 13:48:15 -06001706 bool skipCall = validateCreateSwapchainKHR(device, pCreateInfo, pSwapchain);
Ian Elliott970a2bd2016-06-21 11:08:43 -06001707 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001708
Dustin Graves080069b2016-04-05 13:48:15 -06001709 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001710 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001711 result = my_data->device_dispatch_table->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001712 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001713
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001714 if (result == VK_SUCCESS) {
1715 // Remember the swapchain's handle, and link it to the device:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001716 SwpDevice *pDevice = NULL;
1717 {
1718 auto it = my_data->deviceMap.find(device);
1719 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1720 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001721
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001722 my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
1723 if (pDevice) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001724 pDevice->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001725 }
1726 my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
1727 my_data->swapchainMap[*pSwapchain].imageCount = 0;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001728 my_data->swapchainMap[*pSwapchain].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001729 // Store a pointer to the surface
1730 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001731 SwpInstance *pInstance = (pPhysicalDevice) ? pPhysicalDevice->pInstance : NULL;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001732 layer_data *my_instance_data =
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001733 ((pInstance) ? get_my_data_ptr(get_dispatch_key(pInstance->instance), layer_data_map) : NULL);
1734 SwpSurface *pSurface = ((my_data && pCreateInfo) ? &my_instance_data->surfaceMap[pCreateInfo->surface] : NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001735 my_data->swapchainMap[*pSwapchain].pSurface = pSurface;
1736 if (pSurface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001737 pSurface->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001738 }
1739 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001740 lock.unlock();
1741
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001742 return result;
1743 }
1744 return VK_ERROR_VALIDATION_FAILED_EXT;
1745}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001746
Chia-I Wufccbfe42016-04-28 14:01:30 +08001747VKAPI_ATTR void VKAPI_CALL
1748DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001749 // TODOs:
1750 //
1751 // - Implement a check for validity language that reads: All uses of
Ian Elliotta5d13a92016-04-07 09:05:45 -06001752 // presentable images acquired from pname:swapchain must: have completed
1753 // execution
Dustin Graves080069b2016-04-05 13:48:15 -06001754 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001755 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001756 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001757 SwpDevice *pDevice = NULL;
1758 {
1759 auto it = my_data->deviceMap.find(device);
1760 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1761 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07001762
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001763 // Validate that the swapchain extension was enabled:
1764 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001765 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1766 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
1767 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001768 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001769
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001770 // Regardless of skipCall value, do some internal cleanup:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001771 SwpSwapchain *pSwapchain = NULL;
1772 {
1773 auto it = my_data->swapchainMap.find(swapchain);
1774 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1775 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001776 if (pSwapchain) {
1777 // Delete the SwpSwapchain associated with this swapchain:
1778 if (pSwapchain->pDevice) {
1779 pSwapchain->pDevice->swapchains.erase(swapchain);
1780 if (device != pSwapchain->pDevice->device) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001781 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001782 "%s() called with a different VkDevice than the "
1783 "VkSwapchainKHR was created with.",
1784 __FUNCTION__);
1785 }
1786 }
1787 if (pSwapchain->pSurface) {
1788 pSwapchain->pSurface->swapchains.erase(swapchain);
1789 }
1790 if (pSwapchain->imageCount) {
1791 pSwapchain->images.clear();
1792 }
1793 if ((pAllocator != NULL) != pSwapchain->usedAllocatorToCreate) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001794 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001795 "%s() called with incompatible pAllocator from when "
1796 "the object was created.",
1797 __FUNCTION__);
1798 }
1799 my_data->swapchainMap.erase(swapchain);
1800 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001801 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001802
Dustin Graves080069b2016-04-05 13:48:15 -06001803 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001804 // Call down the call chain:
1805 my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator);
1806 }
1807}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001808
Chia-I Wufccbfe42016-04-28 14:01:30 +08001809VKAPI_ATTR VkResult VKAPI_CALL
1810GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001811 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001812 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001813 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001814 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001815 SwpDevice *pDevice = NULL;
1816 {
1817 auto it = my_data->deviceMap.find(device);
1818 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1819 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07001820
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001821 // Validate that the swapchain extension was enabled:
1822 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001823 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1824 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
1825 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001826 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06001827 SwpSwapchain *pSwapchain = NULL;
1828 {
1829 auto it = my_data->swapchainMap.find(swapchain);
1830 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1831 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001832 if (!pSwapchainImageCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001833 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchainImageCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001834 } else if (pSwapchain && pSwapchainImages) {
1835 // Compare the preliminary value of *pSwapchainImageCount with the
1836 // value this time:
1837 if (pSwapchain->imageCount == 0) {
1838 // Since we haven't recorded a preliminary value of
1839 // *pSwapchainImageCount, that likely means that the application
1840 // didn't previously call this function with a NULL value of
1841 // pSwapchainImages:
1842 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
1843 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1844 device, "pSwapchainImageCount", "pSwapchainImages");
1845 } else if (*pSwapchainImageCount > pSwapchain->imageCount) {
1846 skipCall |= LOG_ERROR_INVALID_COUNT(
1847 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1848 device, "pSwapchainImageCount", "pSwapchainImages",
1849 *pSwapchainImageCount, pSwapchain->imageCount);
1850 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001851 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001852 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001853
Dustin Graves080069b2016-04-05 13:48:15 -06001854 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001855 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001856 result = my_data->device_dispatch_table->GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001857 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001858
Ian Elliott32311832016-02-04 08:17:18 -07001859 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001860 {
1861 auto it = my_data->swapchainMap.find(swapchain);
1862 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1863 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001864 if ((result == VK_SUCCESS) && pSwapchain && !pSwapchainImages && pSwapchainImageCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001865 // Record the result of this preliminary query:
1866 pSwapchain->imageCount = *pSwapchainImageCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001867 } else if ((result == VK_SUCCESS) && pSwapchain && pSwapchainImages &&
1868 pSwapchainImageCount && (*pSwapchainImageCount > 0)) {
1869 // Record the images and their state:
1870 pSwapchain->imageCount = *pSwapchainImageCount;
1871 for (uint32_t i = 0; i < *pSwapchainImageCount; i++) {
1872 pSwapchain->images[i].image = pSwapchainImages[i];
1873 pSwapchain->images[i].pSwapchain = pSwapchain;
1874 pSwapchain->images[i].acquiredByApp = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001875 }
1876 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001877 lock.unlock();
1878
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001879 return result;
1880 }
1881 return VK_ERROR_VALIDATION_FAILED_EXT;
1882}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001883
Chia-I Wufccbfe42016-04-28 14:01:30 +08001884VKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
1885 VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001886 // TODOs:
1887 //
1888 // - Address the timeout. Possibilities include looking at the state of the
1889 // swapchain's images, depending on the timeout value.
1890 // - Implement a check for validity language that reads: If pname:semaphore is
1891 // not sname:VK_NULL_HANDLE it must: be unsignalled
1892 // - Implement a check for validity language that reads: If pname:fence is not
1893 // sname:VK_NULL_HANDLE it must: be unsignalled and mustnot: be associated
1894 // with any other queue command that has not yet completed execution on that
1895 // queue
1896 // - Record/update the state of the swapchain, in case an error occurs
1897 // (e.g. VK_ERROR_OUT_OF_DATE_KHR).
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001898 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001899 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001900 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001901 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001902 SwpDevice *pDevice = NULL;
1903 {
1904 auto it = my_data->deviceMap.find(device);
1905 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1906 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07001907
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001908 // Validate that the swapchain extension was enabled:
1909 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001910 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1911 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
1912 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001913 }
Ian Elliottfa8f0322016-03-23 08:28:54 -06001914 if ((semaphore == VK_NULL_HANDLE) && (fence == VK_NULL_HANDLE)) {
Ian Elliott5da0c962016-03-23 11:13:09 -06001915 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_NO_SYNC_FOR_ACQUIRE,
1916 "%s() called with both the semaphore and fence parameters set to "
Jamie Madillcc4e9322016-05-04 12:20:15 -07001917 "VK_NULL_HANDLE (at least one should be used).", __FUNCTION__);
Ian Elliottfa8f0322016-03-23 08:28:54 -06001918 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06001919 SwpSwapchain *pSwapchain = NULL;
1920 {
1921 auto it = my_data->swapchainMap.find(swapchain);
1922 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1923 }
Ian Elliott5c680282016-04-06 14:29:56 -06001924 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
1925 if (pSwapchain && pPhysicalDevice && pPhysicalDevice->gotSurfaceCapabilities) {
1926 // Look to see if the application has already acquired the maximum
1927 // number of images, and this will push it past the spec-defined
1928 // limits:
1929 uint32_t minImageCount = pPhysicalDevice->surfaceCapabilities.minImageCount;
1930 uint32_t imagesAcquiredByApp = 0;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001931 for (uint32_t i = 0; i < pSwapchain->imageCount; i++) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06001932 if (pSwapchain->images[i].acquiredByApp) {
Ian Elliott5c680282016-04-06 14:29:56 -06001933 imagesAcquiredByApp++;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001934 }
1935 }
Ian Elliott5c680282016-04-06 14:29:56 -06001936 if (imagesAcquiredByApp > (pSwapchain->imageCount - minImageCount)) {
1937 skipCall |= LOG_ERROR(
1938 VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
1939 swapchain, "VkSwapchainKHR",
1940 SWAPCHAIN_APP_ACQUIRES_TOO_MANY_IMAGES,
1941 "%s() called when it cannot succeed. The application has "
1942 "acquired %d image(s) that have not yet been presented. The "
1943 "maximum number of images that the application can "
1944 "simultaneously acquire from this swapchain (including this "
1945 "call to %s()) is %d. That value is derived by subtracting "
1946 "VkSurfaceCapabilitiesKHR::minImageCount (%d) from the number "
1947 "of images in the swapchain (%d) and adding 1.\n",
1948 __FUNCTION__, imagesAcquiredByApp, __FUNCTION__,
1949 (pSwapchain->imageCount - minImageCount + 1),
1950 minImageCount, pSwapchain->imageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001951 }
1952 }
1953 if (!pImageIndex) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001954 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pImageIndex");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001955 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001956 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001957
Dustin Graves080069b2016-04-05 13:48:15 -06001958 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001959 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001960 result = my_data->device_dispatch_table->AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001961 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001962
Ian Elliott32311832016-02-04 08:17:18 -07001963 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001964 {
1965 auto it = my_data->swapchainMap.find(swapchain);
1966 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1967 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001968 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) && pSwapchain) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06001969 // Change the state of the image (now acquired by the application):
1970 pSwapchain->images[*pImageIndex].acquiredByApp = true;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001971 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001972 lock.unlock();
1973
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001974 return result;
1975 }
1976 return VK_ERROR_VALIDATION_FAILED_EXT;
1977}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001978
Chia-I Wufccbfe42016-04-28 14:01:30 +08001979VKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001980 // TODOs:
1981 //
1982 // - Implement a check for validity language that reads: Any given element of
1983 // sname:VkSemaphore in pname:pWaitSemaphores must: refer to a prior signal
1984 // of that sname:VkSemaphore that won't be consumed by any other wait on that
1985 // semaphore
1986 // - Record/update the state of the swapchain, in case an error occurs
1987 // (e.g. VK_ERROR_OUT_OF_DATE_KHR).
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001988 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001989 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001990 layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001991
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001992 if (!pPresentInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001993 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001994 } else {
1995 if (pPresentInfo->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001996 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001997 "VK_STRUCTURE_TYPE_PRESENT_INFO_KHR");
1998 }
1999 if (pPresentInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002000 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002001 }
2002 if (!pPresentInfo->swapchainCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002003 skipCall |= LOG_ERROR_ZERO_VALUE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->swapchainCount");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002004 }
2005 if (!pPresentInfo->pSwapchains) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002006 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pSwapchains");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002007 }
2008 if (!pPresentInfo->pImageIndices) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002009 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pImageIndices");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002010 }
2011 // Note: pPresentInfo->pResults is allowed to be NULL
2012 }
Ian Elliott046ed2c2015-12-30 17:07:17 -07002013
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002014 std::unique_lock<std::mutex> lock(global_lock);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002015 for (uint32_t i = 0; pPresentInfo && (i < pPresentInfo->swapchainCount); i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002016 uint32_t index = pPresentInfo->pImageIndices[i];
Ian Elliott77f46ca2016-05-05 14:10:49 -06002017 SwpSwapchain *pSwapchain = NULL;
2018 {
2019 auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
2020 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2021 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002022 if (pSwapchain) {
2023 if (!pSwapchain->pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002024 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, pSwapchain->pDevice, "VkDevice",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002025 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002026 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2027 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002028 }
2029 if (index >= pSwapchain->imageCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002030 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
2031 SWAPCHAIN_INDEX_TOO_LARGE, "%s() called for an index that is too "
2032 "large (i.e. %d). There are only %d "
2033 "images in this VkSwapchainKHR.\n",
2034 __FUNCTION__, index, pSwapchain->imageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002035 } else {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002036 if (!pSwapchain->images[index].acquiredByApp) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002037 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i],
2038 "VkSwapchainKHR", SWAPCHAIN_INDEX_NOT_IN_USE, "%s() returned an index (i.e. %d) "
Ian Elliotta5d13a92016-04-07 09:05:45 -06002039 "for an image that is not acquired by "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002040 "the application.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002041 __FUNCTION__, index);
2042 }
2043 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06002044 SwpQueue *pQueue = NULL;
2045 {
2046 auto it = my_data->queueMap.find(queue);
2047 pQueue = (it == my_data->queueMap.end()) ? NULL : &it->second;
2048 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002049 SwpSurface *pSurface = pSwapchain->pSurface;
2050 if (pQueue && pSurface && pSurface->numQueueFamilyIndexSupport) {
2051 uint32_t queueFamilyIndex = pQueue->queueFamilyIndex;
2052 // Note: the 1st test is to ensure queueFamilyIndex is in range,
2053 // and the 2nd test is the validation check:
2054 if ((pSurface->numQueueFamilyIndexSupport > queueFamilyIndex) &&
2055 (!pSurface->pQueueFamilyIndexSupport[queueFamilyIndex])) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002056 skipCall |=
2057 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
2058 SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, "%s() called with a swapchain whose "
2059 "surface is not supported for "
2060 "presention on this device with the "
2061 "queueFamilyIndex (i.e. %d) of the "
2062 "given queue.",
2063 __FUNCTION__, queueFamilyIndex);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002064 }
2065 }
2066 }
2067 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002068 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002069
Dustin Graves080069b2016-04-05 13:48:15 -06002070 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002071 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002072 result = my_data->device_dispatch_table->QueuePresentKHR(queue, pPresentInfo);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002073 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002074
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002075 if (pPresentInfo && ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR))) {
2076 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002077 int index = pPresentInfo->pImageIndices[i];
Ian Elliott77f46ca2016-05-05 14:10:49 -06002078 SwpSwapchain *pSwapchain = NULL;
2079 {
2080 auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
2081 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2082 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002083 if (pSwapchain) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002084 // Change the state of the image (no longer acquired by the
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002085 // application):
Ian Elliotta5d13a92016-04-07 09:05:45 -06002086 pSwapchain->images[index].acquiredByApp = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002087 }
2088 }
2089 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002090 lock.unlock();
2091
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002092 return result;
2093 }
2094 return VK_ERROR_VALIDATION_FAILED_EXT;
2095}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002096
Chia-I Wufccbfe42016-04-28 14:01:30 +08002097VKAPI_ATTR void VKAPI_CALL
2098GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
Dustin Graves080069b2016-04-05 13:48:15 -06002099 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002100 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliottc4db6952016-01-21 14:29:45 -07002101
Dustin Graves080069b2016-04-05 13:48:15 -06002102 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002103 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002104 my_data->device_dispatch_table->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
Ian Elliottc4db6952016-01-21 14:29:45 -07002105
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002106 // Remember the queue's handle, and link it to the device:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002107 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002108 SwpDevice *pDevice = NULL;
2109 {
2110 auto it = my_data->deviceMap.find(device);
2111 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2112 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002113 my_data->queueMap[&pQueue].queue = *pQueue;
2114 if (pDevice) {
2115 pDevice->queues[*pQueue] = &my_data->queueMap[*pQueue];
2116 }
2117 my_data->queueMap[&pQueue].pDevice = pDevice;
2118 my_data->queueMap[&pQueue].queueFamilyIndex = queueFamilyIndex;
2119 }
2120}
Ian Elliottc4db6952016-01-21 14:29:45 -07002121
Chia-I Wufccbfe42016-04-28 14:01:30 +08002122VKAPI_ATTR VkResult VKAPI_CALL
2123CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2124 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002125 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002126 VkResult result =
2127 my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002128 if (VK_SUCCESS == result) {
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002129 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -06002130 result = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002131 }
2132 return result;
2133}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002134
Chia-I Wufccbfe42016-04-28 14:01:30 +08002135VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance,
2136 VkDebugReportCallbackEXT msgCallback,
2137 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002138 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2139 my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002140 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002141 layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
2142}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002143
Chia-I Wufccbfe42016-04-28 14:01:30 +08002144VKAPI_ATTR void VKAPI_CALL
2145DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
2146 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002147 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002148 my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix,
2149 pMsg);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002150}
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07002151
Chia-I Wub02600c2016-05-20 07:11:22 +08002152VKAPI_ATTR VkResult VKAPI_CALL
2153EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
2154 return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
2155}
2156
2157VKAPI_ATTR VkResult VKAPI_CALL
2158EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
2159 return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
2160}
2161
2162VKAPI_ATTR VkResult VKAPI_CALL
2163EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
2164 if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
2165 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
2166
2167 return VK_ERROR_LAYER_NOT_PRESENT;
2168}
2169
Chia-I Wufccbfe42016-04-28 14:01:30 +08002170VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
2171 const char *pLayerName, uint32_t *pCount,
2172 VkExtensionProperties *pProperties) {
Chia-I Wu2b481252016-04-28 14:21:13 +08002173 if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
Chia-I Wu045209e2016-04-28 11:21:49 +08002174 return util_GetExtensionProperties(0, nullptr, pCount, pProperties);
Chia-I Wu2b481252016-04-28 14:21:13 +08002175
2176 assert(physicalDevice);
2177
2178 dispatch_key key = get_dispatch_key(physicalDevice);
2179 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
2180 return my_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002181}
2182
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002183static PFN_vkVoidFunction
Chia-I Wu22813c72016-04-28 14:38:57 +08002184intercept_core_instance_command(const char *name);
2185
2186static PFN_vkVoidFunction
2187intercept_khr_surface_command(const char *name, VkInstance instance);
2188
2189static PFN_vkVoidFunction
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002190intercept_core_device_command(const char *name);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002191
Chia-I Wu83245952016-05-05 16:13:19 +08002192static PFN_vkVoidFunction
2193intercept_khr_swapchain_command(const char *name, VkDevice dev);
2194
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002195VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
2196 PFN_vkVoidFunction proc = intercept_core_device_command(funcName);
2197 if (proc)
2198 return proc;
2199
2200 assert(device);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002201
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002202 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06002203
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002204 my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Courtney Goeltzenleuchter1e9e6c82016-03-19 10:38:52 -06002205 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
Chia-I Wu83245952016-05-05 16:13:19 +08002206
2207 proc = intercept_khr_swapchain_command(funcName, device);
2208 if (proc)
2209 return proc;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002210
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002211 if (pDisp->GetDeviceProcAddr == NULL)
2212 return NULL;
2213 return pDisp->GetDeviceProcAddr(device, funcName);
2214}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002215
Chia-I Wufccbfe42016-04-28 14:01:30 +08002216VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wu22813c72016-04-28 14:38:57 +08002217 PFN_vkVoidFunction proc = intercept_core_instance_command(funcName);
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002218 if (!proc)
2219 proc = intercept_core_device_command(funcName);
2220 if (!proc)
2221 proc = intercept_khr_swapchain_command(funcName, VK_NULL_HANDLE);
Chia-I Wu22813c72016-04-28 14:38:57 +08002222 if (proc)
2223 return proc;
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07002224
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002225 assert(instance);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002226
2227 layer_data *my_data;
2228 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002229 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Ian Elliott68124ac2015-10-07 16:18:35 -06002230
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002231 proc = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
2232 if (!proc)
2233 proc = intercept_khr_surface_command(funcName, instance);
Chia-I Wu22813c72016-04-28 14:38:57 +08002234 if (proc)
2235 return proc;
Ian Elliott0b4d6242015-09-22 10:51:24 -06002236
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002237 if (pTable->GetInstanceProcAddr == NULL)
2238 return NULL;
2239 return pTable->GetInstanceProcAddr(instance, funcName);
2240}
Chia-I Wu045209e2016-04-28 11:21:49 +08002241
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002242static PFN_vkVoidFunction
Chia-I Wu22813c72016-04-28 14:38:57 +08002243intercept_core_instance_command(const char *name) {
2244 static const struct {
2245 const char *name;
2246 PFN_vkVoidFunction proc;
2247 } core_instance_commands[] = {
2248 { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
2249 { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
2250 { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) },
2251 { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
2252 { "vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices) },
Chia-I Wub02600c2016-05-20 07:11:22 +08002253 { "vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties) },
2254 { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
2255 { "vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties) },
Chia-I Wu22813c72016-04-28 14:38:57 +08002256 { "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
2257 { "vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties) },
2258 };
2259
2260 for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
2261 if (!strcmp(core_instance_commands[i].name, name))
2262 return core_instance_commands[i].proc;
2263 }
2264
2265 return nullptr;
2266}
2267
2268static PFN_vkVoidFunction
2269intercept_khr_surface_command(const char *name, VkInstance instance) {
2270 static const struct {
2271 const char *name;
2272 PFN_vkVoidFunction proc;
2273 } khr_surface_commands[] = {
2274#ifdef VK_USE_PLATFORM_ANDROID_KHR
2275 { "vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateAndroidSurfaceKHR) },
2276#endif // VK_USE_PLATFORM_ANDROID_KHR
2277#ifdef VK_USE_PLATFORM_MIR_KHR
2278 { "vkCreateMirSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateMirSurfaceKHR) },
2279 { "vkGetPhysicalDeviceMirPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceMirPresentationSupportKHR) },
2280#endif // VK_USE_PLATFORM_MIR_KHR
2281#ifdef VK_USE_PLATFORM_WAYLAND_KHR
2282 { "vkCreateWaylandSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWaylandSurfaceKHR) },
2283 { "vkGetPhysicalDeviceWaylandPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWaylandPresentationSupportKHR) },
2284#endif // VK_USE_PLATFORM_WAYLAND_KHR
2285#ifdef VK_USE_PLATFORM_WIN32_KHR
2286 { "vkCreateWin32SurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWin32SurfaceKHR) },
2287 { "vkGetPhysicalDeviceWin32PresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWin32PresentationSupportKHR) },
2288#endif // VK_USE_PLATFORM_WIN32_KHR
2289#ifdef VK_USE_PLATFORM_XCB_KHR
2290 { "vkCreateXcbSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXcbSurfaceKHR) },
2291 { "vkGetPhysicalDeviceXcbPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXcbPresentationSupportKHR) },
2292#endif // VK_USE_PLATFORM_XCB_KHR
2293#ifdef VK_USE_PLATFORM_XLIB_KHR
2294 { "vkCreateXlibSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXlibSurfaceKHR) },
2295 { "vkGetPhysicalDeviceXlibPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXlibPresentationSupportKHR) },
2296#endif // VK_USE_PLATFORM_XLIB_KHR
2297 { "vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySurfaceKHR) },
2298 { "vkGetPhysicalDeviceSurfaceSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceSupportKHR) },
2299 { "vkGetPhysicalDeviceSurfaceCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceCapabilitiesKHR) },
2300 { "vkGetPhysicalDeviceSurfaceFormatsKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceFormatsKHR) },
2301 { "vkGetPhysicalDeviceSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfacePresentModesKHR) },
2302 };
2303
2304 // do not check if VK_KHR_*_surface is enabled (why?)
2305
2306 for (size_t i = 0; i < ARRAY_SIZE(khr_surface_commands); i++) {
2307 if (!strcmp(khr_surface_commands[i].name, name))
2308 return khr_surface_commands[i].proc;
2309 }
2310
2311 return nullptr;
2312}
2313
2314static PFN_vkVoidFunction
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002315intercept_core_device_command(const char *name) {
2316 static const struct {
2317 const char *name;
2318 PFN_vkVoidFunction proc;
2319 } core_device_commands[] = {
2320 { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
2321 { "vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice) },
2322 { "vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue) },
2323 };
2324
2325 for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) {
2326 if (!strcmp(core_device_commands[i].name, name))
2327 return core_device_commands[i].proc;
2328 }
2329
2330 return nullptr;
2331}
2332
Chia-I Wu83245952016-05-05 16:13:19 +08002333static PFN_vkVoidFunction
2334intercept_khr_swapchain_command(const char *name, VkDevice dev) {
2335 static const struct {
2336 const char *name;
2337 PFN_vkVoidFunction proc;
2338 } khr_swapchain_commands[] = {
2339 { "vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR) },
2340 { "vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR) },
2341 { "vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR) },
2342 { "vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR) },
2343 { "vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR) },
2344 };
2345
2346 // do not check if VK_KHR_swapchain is enabled (why?)
2347
2348 for (size_t i = 0; i < ARRAY_SIZE(khr_swapchain_commands); i++) {
2349 if (!strcmp(khr_swapchain_commands[i].name, name))
2350 return khr_swapchain_commands[i].proc;
2351 }
2352
2353 return nullptr;
2354}
2355
Chia-I Wu516b5082016-04-28 11:27:46 +08002356} // namespace swapchain
2357
2358// vk_layer_logging.h expects these to be defined
2359
Chia-I Wufccbfe42016-04-28 14:01:30 +08002360VKAPI_ATTR VkResult VKAPI_CALL
Chia-I Wu516b5082016-04-28 11:27:46 +08002361vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2362 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002363 return swapchain::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Chia-I Wu516b5082016-04-28 11:27:46 +08002364}
2365
Chia-I Wufccbfe42016-04-28 14:01:30 +08002366VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance,
Chia-I Wu516b5082016-04-28 11:27:46 +08002367 VkDebugReportCallbackEXT msgCallback,
2368 const VkAllocationCallbacks *pAllocator) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002369 swapchain::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Chia-I Wu516b5082016-04-28 11:27:46 +08002370}
2371
Chia-I Wufccbfe42016-04-28 14:01:30 +08002372VKAPI_ATTR void VKAPI_CALL
Chia-I Wu516b5082016-04-28 11:27:46 +08002373vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
2374 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002375 swapchain::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
Chia-I Wu516b5082016-04-28 11:27:46 +08002376}
2377
Chia-I Wub02600c2016-05-20 07:11:22 +08002378// loader-layer interface v0, just wrappers since there is only a layer
Chia-I Wu516b5082016-04-28 11:27:46 +08002379
Chia-I Wu045209e2016-04-28 11:21:49 +08002380VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2381vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002382 return swapchain::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002383}
2384
2385VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2386vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002387 return swapchain::EnumerateInstanceLayerProperties(pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002388}
2389
2390VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2391vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002392 // the layer command handles VK_NULL_HANDLE just fine internally
2393 assert(physicalDevice == VK_NULL_HANDLE);
2394 return swapchain::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
Chia-I Wu516b5082016-04-28 11:27:46 +08002395}
2396
2397VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
2398 const char *pLayerName, uint32_t *pCount,
2399 VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002400 // the layer command handles VK_NULL_HANDLE just fine internally
2401 assert(physicalDevice == VK_NULL_HANDLE);
Chia-I Wu2b481252016-04-28 14:21:13 +08002402 return swapchain::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
Chia-I Wu516b5082016-04-28 11:27:46 +08002403}
2404
2405VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002406 return swapchain::GetDeviceProcAddr(dev, funcName);
Chia-I Wu516b5082016-04-28 11:27:46 +08002407}
2408
2409VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002410 return swapchain::GetInstanceProcAddr(instance, funcName);
Chia-I Wu045209e2016-04-28 11:21:49 +08002411}