blob: 96691f143ce9eef873057236bd4568b211c7c742 [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 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700403
Dustin Graves080069b2016-04-05 13:48:15 -0600404 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700405 // Call down the call chain:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600406 lock.unlock();
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 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700425 return result;
426 }
427 return VK_ERROR_VALIDATION_FAILED_EXT;
428}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700429#endif // VK_USE_PLATFORM_ANDROID_KHR
430
431#ifdef VK_USE_PLATFORM_MIR_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800432VKAPI_ATTR VkResult VKAPI_CALL
433CreateMirSurfaceKHR(VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
434 VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700435 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600436 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700437 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600438 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600439 SwpInstance *pInstance = NULL;
440 {
441 auto it = my_data->instanceMap.find(instance);
442 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
443 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700444
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700445 // Validate that the platform extension was enabled:
446 if (pInstance && !pInstance->mirSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700447 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
448 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
449 VK_KHR_MIR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700450 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700451
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700452 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700453 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700454 } else {
455 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700456 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700457 "VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR");
458 }
459 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700460 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700461 }
462 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700463
Dustin Graves080069b2016-04-05 13:48:15 -0600464 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700465 // Call down the call chain:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600466 lock.unlock();
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700467 result = my_data->instance_dispatch_table->CreateMirSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600468 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700469
Ian Elliott32311832016-02-04 08:17:18 -0700470 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600471 {
472 auto it = my_data->instanceMap.find(instance);
473 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
474 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700475 if ((result == VK_SUCCESS) && pInstance && pSurface) {
476 // Record the VkSurfaceKHR returned by the ICD:
477 my_data->surfaceMap[*pSurface].surface = *pSurface;
478 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700479 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700480 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
481 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
482 // Point to the associated SwpInstance:
483 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
484 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700485 return result;
486 }
487 return VK_ERROR_VALIDATION_FAILED_EXT;
488}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700489
Chia-I Wufccbfe42016-04-28 14:01:30 +0800490VKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceMirPresentationSupportKHR(VkPhysicalDevice physicalDevice,
491 uint32_t queueFamilyIndex,
492 MirConnection *connection) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700493 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600494 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700495 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600496 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600497 SwpPhysicalDevice *pPhysicalDevice = NULL;
498 {
499 auto it = my_data->physicalDeviceMap.find(physicalDevice);
500 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
501 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700502
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700503 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700504 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->mirSurfaceExtensionEnabled) {
505 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700506 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700507 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
508 VK_KHR_MIR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700509 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700510 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
511 skipCall |=
512 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
513 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700514 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600515 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700516
Dustin Graves080069b2016-04-05 13:48:15 -0600517 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700518 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700519 result = my_data->instance_dispatch_table->GetPhysicalDeviceMirPresentationSupportKHR(physicalDevice, queueFamilyIndex,
520 connection);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700521 }
522 return result;
523}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700524#endif // VK_USE_PLATFORM_MIR_KHR
525
526#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800527VKAPI_ATTR VkResult VKAPI_CALL
528CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
529 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700530 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600531 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700532 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600533 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600534 SwpInstance *pInstance = NULL;
535 {
536 auto it = my_data->instanceMap.find(instance);
537 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
538 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700539
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700540 // Validate that the platform extension was enabled:
541 if (pInstance && !pInstance->waylandSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700542 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
543 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
544 VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700545 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700546
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700547 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700548 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700549 } else {
550 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700551 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700552 "VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR");
553 }
554 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700555 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700556 }
557 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700558
Dustin Graves080069b2016-04-05 13:48:15 -0600559 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700560 // Call down the call chain:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600561 lock.unlock();
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700562 result = my_data->instance_dispatch_table->CreateWaylandSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600563 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700564
Ian Elliott32311832016-02-04 08:17:18 -0700565 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600566 {
567 auto it = my_data->instanceMap.find(instance);
568 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
569 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700570 if ((result == VK_SUCCESS) && pInstance && pSurface) {
571 // Record the VkSurfaceKHR returned by the ICD:
572 my_data->surfaceMap[*pSurface].surface = *pSurface;
573 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700574 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700575 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
576 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
577 // Point to the associated SwpInstance:
578 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
579 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700580 return result;
581 }
582 return VK_ERROR_VALIDATION_FAILED_EXT;
583}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700584
Chia-I Wufccbfe42016-04-28 14:01:30 +0800585VKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,
586 uint32_t queueFamilyIndex,
587 struct wl_display *display) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700588 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600589 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700590 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600591 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600592 SwpPhysicalDevice *pPhysicalDevice = NULL;
593 {
594 auto it = my_data->physicalDeviceMap.find(physicalDevice);
595 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
596 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700597
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700598 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700599 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->waylandSurfaceExtensionEnabled) {
600 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700601 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700602 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
603 VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700604 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700605 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
606 skipCall |=
607 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
608 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700609 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600610 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700611
Dustin Graves080069b2016-04-05 13:48:15 -0600612 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700613 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700614 result = my_data->instance_dispatch_table->GetPhysicalDeviceWaylandPresentationSupportKHR(physicalDevice, queueFamilyIndex,
615 display);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700616 }
617 return result;
618}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700619#endif // VK_USE_PLATFORM_WAYLAND_KHR
620
621#ifdef VK_USE_PLATFORM_WIN32_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800622VKAPI_ATTR VkResult VKAPI_CALL
623CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
624 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700625 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600626 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700627 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600628 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600629 SwpInstance *pInstance = NULL;
630 {
631 auto it = my_data->instanceMap.find(instance);
632 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
633 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700634
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700635 // Validate that the platform extension was enabled:
636 if (pInstance && !pInstance->win32SurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700637 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
638 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
639 VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700640 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700641
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700642 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700643 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700644 } else {
645 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700646 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700647 "VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR");
648 }
649 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700650 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700651 }
652 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700653
Dustin Graves080069b2016-04-05 13:48:15 -0600654 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700655 // Call down the call chain:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600656 lock.unlock();
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700657 result = my_data->instance_dispatch_table->CreateWin32SurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600658 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700659
Ian Elliott32311832016-02-04 08:17:18 -0700660 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600661 {
662 auto it = my_data->instanceMap.find(instance);
663 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
664 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700665 if ((result == VK_SUCCESS) && pInstance && pSurface) {
666 // Record the VkSurfaceKHR returned by the ICD:
667 my_data->surfaceMap[*pSurface].surface = *pSurface;
668 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700669 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700670 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
671 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
672 // Point to the associated SwpInstance:
673 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
674 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700675 return result;
676 }
677 return VK_ERROR_VALIDATION_FAILED_EXT;
678}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700679
Chia-I Wufccbfe42016-04-28 14:01:30 +0800680VKAPI_ATTR VkBool32 VKAPI_CALL
681GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700682 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600683 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700684 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600685 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600686 SwpPhysicalDevice *pPhysicalDevice = NULL;
687 {
688 auto it = my_data->physicalDeviceMap.find(physicalDevice);
689 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
690 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700691
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700692 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700693 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->win32SurfaceExtensionEnabled) {
694 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700695 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700696 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
697 VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700698 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700699 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
700 skipCall |=
701 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
702 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700703 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600704 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700705
Dustin Graves080069b2016-04-05 13:48:15 -0600706 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700707 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700708 result = my_data->instance_dispatch_table->GetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700709 }
710 return result;
711}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700712#endif // VK_USE_PLATFORM_WIN32_KHR
713
714#ifdef VK_USE_PLATFORM_XCB_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800715VKAPI_ATTR VkResult VKAPI_CALL
716CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700717 VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700718 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600719 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700720 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600721 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600722 SwpInstance *pInstance = NULL;
723 {
724 auto it = my_data->instanceMap.find(instance);
725 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
726 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700727
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700728 // Validate that the platform extension was enabled:
729 if (pInstance && !pInstance->xcbSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700730 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
731 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
732 VK_KHR_XCB_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700733 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700734
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700735 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700736 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700737 } else {
738 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700739 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700740 "VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR");
741 }
742 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700743 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700744 }
745 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700746
Dustin Graves080069b2016-04-05 13:48:15 -0600747 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700748 // Call down the call chain:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600749 lock.unlock();
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700750 result = my_data->instance_dispatch_table->CreateXcbSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600751 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700752
Ian Elliott32311832016-02-04 08:17:18 -0700753 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600754 {
755 auto it = my_data->instanceMap.find(instance);
756 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
757 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700758 if ((result == VK_SUCCESS) && pInstance && pSurface) {
759 // Record the VkSurfaceKHR returned by the ICD:
760 my_data->surfaceMap[*pSurface].surface = *pSurface;
761 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700762 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700763 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
764 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
765 // Point to the associated SwpInstance:
766 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
767 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700768 return result;
769 }
770 return VK_ERROR_VALIDATION_FAILED_EXT;
771}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700772
Chia-I Wufccbfe42016-04-28 14:01:30 +0800773VKAPI_ATTR VkBool32 VKAPI_CALL
774GetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex,
775 xcb_connection_t *connection, xcb_visualid_t visual_id) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700776 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600777 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700778 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600779 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600780 SwpPhysicalDevice *pPhysicalDevice = NULL;
781 {
782 auto it = my_data->physicalDeviceMap.find(physicalDevice);
783 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
784 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700785
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700786 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700787 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->xcbSurfaceExtensionEnabled) {
788 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700789 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700790 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
791 VK_KHR_XCB_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700792 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700793 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
794 skipCall |=
795 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
796 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700797 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600798 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700799
Dustin Graves080069b2016-04-05 13:48:15 -0600800 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700801 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700802 result = my_data->instance_dispatch_table->GetPhysicalDeviceXcbPresentationSupportKHR(physicalDevice, queueFamilyIndex,
803 connection, visual_id);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700804 }
805 return result;
806}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700807#endif // VK_USE_PLATFORM_XCB_KHR
808
809#ifdef VK_USE_PLATFORM_XLIB_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800810VKAPI_ATTR VkResult VKAPI_CALL
811CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
812 VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700813 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600814 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700815 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600816 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600817 SwpInstance *pInstance = NULL;
818 {
819 auto it = my_data->instanceMap.find(instance);
820 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
821 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700822
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700823 // Validate that the platform extension was enabled:
824 if (pInstance && !pInstance->xlibSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700825 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
826 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
827 VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700828 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700829
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700830 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700831 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700832 } else {
833 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700834 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700835 "VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR");
836 }
837 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700838 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700839 }
840 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700841
Dustin Graves080069b2016-04-05 13:48:15 -0600842 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700843 // Call down the call chain:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600844 lock.unlock();
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700845 result = my_data->instance_dispatch_table->CreateXlibSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600846 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700847
Ian Elliott32311832016-02-04 08:17:18 -0700848 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600849 {
850 auto it = my_data->instanceMap.find(instance);
851 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
852 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700853 if ((result == VK_SUCCESS) && pInstance && pSurface) {
854 // Record the VkSurfaceKHR returned by the ICD:
855 my_data->surfaceMap[*pSurface].surface = *pSurface;
856 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700857 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700858 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
859 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
860 // Point to the associated SwpInstance:
861 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
862 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700863 return result;
864 }
865 return VK_ERROR_VALIDATION_FAILED_EXT;
866}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700867
Chia-I Wufccbfe42016-04-28 14:01:30 +0800868VKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
869 uint32_t queueFamilyIndex,
870 Display *dpy, VisualID visualID) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700871 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600872 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700873 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600874 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600875 SwpPhysicalDevice *pPhysicalDevice = NULL;
876 {
877 auto it = my_data->physicalDeviceMap.find(physicalDevice);
878 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
879 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700880
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700881 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700882 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->xlibSurfaceExtensionEnabled) {
883 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700884 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700885 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
886 VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700887 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700888 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
889 skipCall |=
890 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
891 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700892 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600893 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700894
Dustin Graves080069b2016-04-05 13:48:15 -0600895 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700896 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700897 result = my_data->instance_dispatch_table->GetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex,
898 dpy, visualID);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700899 }
900 return result;
901}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700902#endif // VK_USE_PLATFORM_XLIB_KHR
903
Chia-I Wufccbfe42016-04-28 14:01:30 +0800904VKAPI_ATTR void VKAPI_CALL
905DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) {
Dustin Graves080069b2016-04-05 13:48:15 -0600906 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700907 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600908 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600909 SwpSurface *pSurface = NULL;
910 {
911 auto it = my_data->surfaceMap.find(surface);
912 pSurface = (it == my_data->surfaceMap.end()) ? NULL : &it->second;
913 }
914 SwpInstance *pInstance = NULL;
915 {
916 auto it = my_data->instanceMap.find(instance);
917 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
918 }
Ian Elliottf6b8c782016-04-29 13:03:17 -0600919
920 // Validate that the platform extension was enabled:
921 if (pInstance && !pInstance->surfaceExtensionEnabled) {
922 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
923 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
924 VK_KHR_SURFACE_EXTENSION_NAME);
925 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700926
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700927 // Regardless of skipCall value, do some internal cleanup:
928 if (pSurface) {
929 // Delete the SwpSurface associated with this surface:
930 if (pSurface->pInstance) {
931 pSurface->pInstance->surfaces.erase(surface);
932 }
933 if (!pSurface->swapchains.empty()) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700934 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700935 "%s() called before all of its associated "
936 "VkSwapchainKHRs were destroyed.",
937 __FUNCTION__);
938 // Empty and then delete all SwpSwapchain's
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700939 for (auto it = pSurface->swapchains.begin(); it != pSurface->swapchains.end(); it++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700940 // Delete all SwpImage's
941 it->second->images.clear();
942 // In case the swapchain's device hasn't been destroyed yet
943 // (which isn't likely, but is possible), delete its
944 // association with this swapchain (i.e. so we can't point to
945 // this swpchain from that device, later on):
946 if (it->second->pDevice) {
947 it->second->pDevice->swapchains.clear();
948 }
949 }
950 pSurface->swapchains.clear();
951 }
952 if ((pAllocator != NULL) != pSurface->usedAllocatorToCreate) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700953 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700954 "%s() called with incompatible pAllocator from when "
955 "the object was created.",
956 __FUNCTION__);
957 }
958 my_data->surfaceMap.erase(surface);
959 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600960 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700961
Dustin Graves080069b2016-04-05 13:48:15 -0600962 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700963 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700964 my_data->instance_dispatch_table->DestroySurfaceKHR(instance, surface, pAllocator);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700965 }
966}
967
Chia-I Wufccbfe42016-04-28 14:01:30 +0800968VKAPI_ATTR VkResult VKAPI_CALL
969EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700970 VkResult result = VK_SUCCESS;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700971 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700972
973 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700974 result = my_data->instance_dispatch_table->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
Ian Elliott32311832016-02-04 08:17:18 -0700975
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600976 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600977 SwpInstance *pInstance = NULL;
978 {
979 auto it = my_data->instanceMap.find(instance);
980 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
981 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700982 if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices && (*pPhysicalDeviceCount > 0)) {
Ian Elliott32311832016-02-04 08:17:18 -0700983 // Record the VkPhysicalDevices returned by the ICD:
984 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700985 my_data->physicalDeviceMap[pPhysicalDevices[i]].physicalDevice = pPhysicalDevices[i];
Ian Elliott32311832016-02-04 08:17:18 -0700986 my_data->physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance;
987 my_data->physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL;
988 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotQueueFamilyPropertyCount = false;
989 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotSurfaceCapabilities = false;
990 my_data->physicalDeviceMap[pPhysicalDevices[i]].surfaceFormatCount = 0;
991 my_data->physicalDeviceMap[pPhysicalDevices[i]].pSurfaceFormats = NULL;
992 my_data->physicalDeviceMap[pPhysicalDevices[i]].presentModeCount = 0;
993 my_data->physicalDeviceMap[pPhysicalDevices[i]].pPresentModes = NULL;
994 // Point to the associated SwpInstance:
995 if (pInstance) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700996 pInstance->physicalDevices[pPhysicalDevices[i]] = &my_data->physicalDeviceMap[pPhysicalDevices[i]];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700997 }
998 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700999 }
Ian Elliotta3c69bc2016-02-04 15:34:59 -07001000 return result;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001001}
1002
Chia-I Wufccbfe42016-04-28 14:01:30 +08001003VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice physicalDevice,
1004 const VkDeviceCreateInfo *pCreateInfo,
1005 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Chia-I Wua6737532016-04-28 16:04:15 +08001006 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001007 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
1008
1009 assert(chain_info->u.pLayerInfo);
1010 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
1011 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Chia-I Wua6737532016-04-28 16:04:15 +08001012 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001013 if (fpCreateDevice == NULL) {
1014 return VK_ERROR_INITIALIZATION_FAILED;
1015 }
1016
1017 // Advance the link info for the next element on the chain
1018 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
1019
1020 VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1021 if (result != VK_SUCCESS) {
1022 return result;
1023 }
1024
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001025 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001026 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
1027
1028 // Setup device dispatch table
1029 my_device_data->device_dispatch_table = new VkLayerDispatchTable;
1030 layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
1031
1032 my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
1033 createDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice);
1034
1035 return result;
1036}
1037
Chia-I Wufccbfe42016-04-28 14:01:30 +08001038VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001039 dispatch_key key = get_dispatch_key(device);
1040 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001041
1042 // Call down the call chain:
1043 my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
1044
1045 // Do some internal cleanup:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001046 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001047 SwpDevice *pDevice = NULL;
1048 {
1049 auto it = my_data->deviceMap.find(device);
1050 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1051 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001052 if (pDevice) {
1053 // Delete the SwpDevice associated with this device:
1054 if (pDevice->pPhysicalDevice) {
1055 pDevice->pPhysicalDevice->pDevice = NULL;
1056 }
1057 if (!pDevice->swapchains.empty()) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001058 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001059 "%s() called before all of its associated "
1060 "VkSwapchainKHRs were destroyed.",
1061 __FUNCTION__);
1062 // Empty and then delete all SwpSwapchain's
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001063 for (auto it = pDevice->swapchains.begin(); it != pDevice->swapchains.end(); it++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001064 // Delete all SwpImage's
1065 it->second->images.clear();
1066 // In case the swapchain's surface hasn't been destroyed yet
1067 // (which is likely) delete its association with this swapchain
1068 // (i.e. so we can't point to this swpchain from that surface,
1069 // later on):
1070 if (it->second->pSurface) {
1071 it->second->pSurface->swapchains.clear();
1072 }
1073 }
1074 pDevice->swapchains.clear();
1075 }
1076 my_data->deviceMap.erase(device);
1077 }
1078 delete my_data->device_dispatch_table;
1079 layer_data_map.erase(key);
1080}
1081
Chia-I Wufccbfe42016-04-28 14:01:30 +08001082VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
1083 uint32_t queueFamilyIndex, VkSurfaceKHR surface,
1084 VkBool32 *pSupported) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001085 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001086 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001087 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001088 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001089 SwpPhysicalDevice *pPhysicalDevice = NULL;
1090 {
1091 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1092 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1093 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001094
1095 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001096 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1097 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001098 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001099 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1100 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001101 }
1102 if (!pPhysicalDevice->gotQueueFamilyPropertyCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001103 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, "VkPhysicalDevice",
1104 SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES, "%s() called before calling the "
1105 "vkGetPhysicalDeviceQueueFamilyProperties "
1106 "function.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001107 __FUNCTION__);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001108 } else if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
1109 skipCall |=
1110 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
1111 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001112 }
1113 if (!pSupported) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001114 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSupported");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001115 }
1116
Dustin Graves080069b2016-04-05 13:48:15 -06001117 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001118 // Call down the call chain:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001119 lock.unlock();
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001120 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface,
1121 pSupported);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001122 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001123
Ian Elliott32311832016-02-04 08:17:18 -07001124 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001125 {
1126 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1127 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1128 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001129 if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
1130 // Record the result of this query:
1131 SwpInstance *pInstance = pPhysicalDevice->pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001132 SwpSurface *pSurface = (pInstance) ? pInstance->surfaces[surface] : NULL;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001133 if (pSurface) {
1134 pPhysicalDevice->supportedSurfaces[surface] = pSurface;
1135 if (!pSurface->numQueueFamilyIndexSupport) {
1136 if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001137 pSurface->pQueueFamilyIndexSupport =
1138 (VkBool32 *)malloc(pPhysicalDevice->numOfQueueFamilies * sizeof(VkBool32));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001139 if (pSurface->pQueueFamilyIndexSupport != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001140 pSurface->numQueueFamilyIndexSupport = pPhysicalDevice->numOfQueueFamilies;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001141 }
1142 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001143 }
1144 if (pSurface->numQueueFamilyIndexSupport) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001145 pSurface->pQueueFamilyIndexSupport[queueFamilyIndex] = *pSupported;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001146 }
1147 }
1148 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001149 return result;
1150 }
1151 return VK_ERROR_VALIDATION_FAILED_EXT;
1152}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001153
Chia-I Wufccbfe42016-04-28 14:01:30 +08001154VKAPI_ATTR VkResult VKAPI_CALL
1155GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
1156 VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001157 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001158 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001159 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001160 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001161 SwpPhysicalDevice *pPhysicalDevice = NULL;
1162 {
1163 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1164 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1165 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001166
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001167 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001168 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1169 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001170 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001171 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1172 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001173 }
1174 if (!pSurfaceCapabilities) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001175 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceCapabilities");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001176 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001177
Dustin Graves080069b2016-04-05 13:48:15 -06001178 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001179 // Call down the call chain:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001180 lock.unlock();
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001181 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface,
1182 pSurfaceCapabilities);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001183 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001184
Ian Elliott32311832016-02-04 08:17:18 -07001185 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001186 {
1187 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1188 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1189 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001190 if ((result == VK_SUCCESS) && pPhysicalDevice) {
1191 // Record the result of this query:
1192 pPhysicalDevice->gotSurfaceCapabilities = true;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001193 // FIXME: NEED TO COPY THIS DATA, BECAUSE pSurfaceCapabilities POINTS TO APP-ALLOCATED DATA
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001194 pPhysicalDevice->surfaceCapabilities = *pSurfaceCapabilities;
1195 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001196 return result;
1197 }
1198 return VK_ERROR_VALIDATION_FAILED_EXT;
1199}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001200
Chia-I Wufccbfe42016-04-28 14:01:30 +08001201VKAPI_ATTR VkResult VKAPI_CALL
1202GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount,
1203 VkSurfaceFormatKHR *pSurfaceFormats) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001204 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001205 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001206 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001207 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001208 SwpPhysicalDevice *pPhysicalDevice = NULL;
1209 {
1210 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1211 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1212 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001213
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001214 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001215 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1216 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001217 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001218 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1219 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001220 }
1221 if (!pSurfaceFormatCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001222 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceFormatCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001223 } else if (pPhysicalDevice && pSurfaceFormats) {
1224 // Compare the preliminary value of *pSurfaceFormatCount with the
1225 // value this time:
1226 if (pPhysicalDevice->surfaceFormatCount == 0) {
1227 // Since we haven't recorded a preliminary value of
1228 // *pSurfaceFormatCount, that likely means that the application
1229 // didn't previously call this function with a NULL value of
1230 // pSurfaceFormats:
1231 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
1232 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1233 physicalDevice, "pSurfaceFormatCount", "pSurfaceFormats");
1234 } else if (*pSurfaceFormatCount > pPhysicalDevice->surfaceFormatCount) {
1235 skipCall |= LOG_ERROR_INVALID_COUNT(
1236 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1237 physicalDevice, "pSurfaceFormatCount", "pSurfaceFormats",
1238 *pSurfaceFormatCount, pPhysicalDevice->surfaceFormatCount);
1239 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001240 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001241
Dustin Graves080069b2016-04-05 13:48:15 -06001242 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001243 // Call down the call chain:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001244 lock.unlock();
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001245 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount,
1246 pSurfaceFormats);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001247 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001248
Ian Elliott32311832016-02-04 08:17:18 -07001249 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001250 {
1251 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1252 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1253 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001254 if ((result == VK_SUCCESS) && pPhysicalDevice && !pSurfaceFormats && pSurfaceFormatCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001255 // Record the result of this preliminary query:
1256 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001257 } else if ((result == VK_SUCCESS) && pPhysicalDevice &&
1258 pSurfaceFormats && pSurfaceFormatCount &&
1259 (*pSurfaceFormatCount > 0)) {
1260 // Record the result of this query:
1261 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
1262 pPhysicalDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)malloc(*pSurfaceFormatCount * sizeof(VkSurfaceFormatKHR));
1263 if (pPhysicalDevice->pSurfaceFormats) {
1264 for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) {
1265 pPhysicalDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001266 }
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001267 } else {
1268 pPhysicalDevice->surfaceFormatCount = 0;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001269 }
1270 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001271 return result;
1272 }
1273 return VK_ERROR_VALIDATION_FAILED_EXT;
1274}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001275
Chia-I Wufccbfe42016-04-28 14:01:30 +08001276VKAPI_ATTR VkResult VKAPI_CALL
1277GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pPresentModeCount,
1278 VkPresentModeKHR *pPresentModes) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001279 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001280 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001281 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001282 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001283 SwpPhysicalDevice *pPhysicalDevice = NULL;
1284 {
1285 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1286 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1287 }
Ian Elliott07adb112016-01-05 12:51:03 -07001288
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001289 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001290 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1291 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001292 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001293 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1294 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001295 }
1296 if (!pPresentModeCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001297 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pPresentModeCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001298 } else if (pPhysicalDevice && pPresentModes) {
1299 // Compare the preliminary value of *pPresentModeCount with the
1300 // value this time:
1301 if (pPhysicalDevice->presentModeCount == 0) {
1302 // Since we haven't recorded a preliminary value of
1303 // *pPresentModeCount, that likely means that the application
1304 // didn't previously call this function with a NULL value of
1305 // pPresentModes:
1306 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
1307 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1308 physicalDevice, "pPresentModeCount", "pPresentModes");
1309 } else if (*pPresentModeCount > pPhysicalDevice->presentModeCount) {
1310 skipCall |= LOG_ERROR_INVALID_COUNT(
1311 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1312 physicalDevice, "pPresentModeCount", "pPresentModes",
1313 *pPresentModeCount, pPhysicalDevice->presentModeCount);
1314 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001315 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001316
Dustin Graves080069b2016-04-05 13:48:15 -06001317 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001318 // Call down the call chain:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001319 lock.unlock();
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001320 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface,
1321 pPresentModeCount, pPresentModes);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001322 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001323
Ian Elliott32311832016-02-04 08:17:18 -07001324 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001325 {
1326 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1327 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1328 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001329 if ((result == VK_SUCCESS) && pPhysicalDevice && !pPresentModes && pPresentModeCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001330 // Record the result of this preliminary query:
1331 pPhysicalDevice->presentModeCount = *pPresentModeCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001332 } else if ((result == VK_SUCCESS) && pPhysicalDevice &&
1333 pPresentModes && pPresentModeCount &&
1334 (*pPresentModeCount > 0)) {
1335 // Record the result of this query:
1336 pPhysicalDevice->presentModeCount = *pPresentModeCount;
1337 pPhysicalDevice->pPresentModes = (VkPresentModeKHR *)malloc(*pPresentModeCount * sizeof(VkPresentModeKHR));
1338 if (pPhysicalDevice->pPresentModes) {
1339 for (uint32_t i = 0; i < *pPresentModeCount; i++) {
1340 pPhysicalDevice->pPresentModes[i] = pPresentModes[i];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001341 }
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001342 } else {
1343 pPhysicalDevice->presentModeCount = 0;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001344 }
1345 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001346 return result;
1347 }
1348 return VK_ERROR_VALIDATION_FAILED_EXT;
1349}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001350
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001351// This function does the up-front validation work for vkCreateSwapchainKHR(),
Dustin Graves080069b2016-04-05 13:48:15 -06001352// and returns true if a logging callback indicates that the call down the
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001353// chain should be skipped:
Dustin Graves080069b2016-04-05 13:48:15 -06001354static bool validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, VkSwapchainKHR *pSwapchain) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001355 // TODO: Validate cases of re-creating a swapchain (the current code
1356 // assumes a new swapchain is being created).
Dustin Graves080069b2016-04-05 13:48:15 -06001357 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001358 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1359 char fn[] = "vkCreateSwapchainKHR";
Ian Elliott77f46ca2016-05-05 14:10:49 -06001360 SwpDevice *pDevice = NULL;
1361 {
1362 auto it = my_data->deviceMap.find(device);
1363 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1364 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001365
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001366 // Validate that the swapchain extension was enabled:
1367 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001368 return LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1369 "%s() called even though the %s extension was not enabled for this VkDevice.", fn,
1370 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001371 }
1372 if (!pCreateInfo) {
Ian Elliott432a3172016-05-09 12:33:47 -06001373 return LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001374 } else {
1375 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001376 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001377 "VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR");
1378 }
1379 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001380 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001381 }
1382 }
1383 if (!pSwapchain) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001384 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchain");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001385 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001386
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001387 // Keep around a useful pointer to pPhysicalDevice:
1388 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001389
Mark Lobodzinskid40b2db2016-02-25 13:56:57 -07001390 // Validate pCreateInfo values with result of
1391 // vkGetPhysicalDeviceQueueFamilyProperties
1392 if (pPhysicalDevice && pPhysicalDevice->gotQueueFamilyPropertyCount) {
Michael Mc Donnell75ecdb72016-04-03 14:47:51 -07001393 for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001394 if (pCreateInfo->pQueueFamilyIndices[i] >= pPhysicalDevice->numOfQueueFamilies) {
1395 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
1396 "VkPhysicalDevice", pCreateInfo->pQueueFamilyIndices[i],
1397 pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinskid40b2db2016-02-25 13:56:57 -07001398 }
1399 }
1400 }
1401
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001402 // Validate pCreateInfo values with the results of
1403 // vkGetPhysicalDeviceSurfaceCapabilitiesKHR():
1404 if (!pPhysicalDevice || !pPhysicalDevice->gotSurfaceCapabilities) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001405 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001406 "%s() called before calling "
1407 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1408 fn);
1409 } else if (pCreateInfo) {
1410 // Validate pCreateInfo->surface to make sure that
1411 // vkGetPhysicalDeviceSurfaceSupportKHR() reported this as a supported
1412 // surface:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001413 SwpSurface *pSurface = ((pPhysicalDevice) ? pPhysicalDevice->supportedSurfaces[pCreateInfo->surface] : NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001414 if (!pSurface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001415 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001416 "%s() called with pCreateInfo->surface that "
1417 "was not returned by "
1418 "vkGetPhysicalDeviceSurfaceSupportKHR() "
1419 "for the device.",
1420 fn);
1421 }
Ian Elliott4f147fc2016-01-20 08:52:08 -07001422
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001423 // Validate pCreateInfo->minImageCount against
1424 // VkSurfaceCapabilitiesKHR::{min|max}ImageCount:
1425 VkSurfaceCapabilitiesKHR *pCapabilities = &pPhysicalDevice->surfaceCapabilities;
1426 if ((pCreateInfo->minImageCount < pCapabilities->minImageCount) ||
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001427 ((pCapabilities->maxImageCount > 0) && (pCreateInfo->minImageCount > pCapabilities->maxImageCount))) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001428 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001429 SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT, "%s() called with pCreateInfo->minImageCount "
1430 "= %d, which is outside the bounds returned "
1431 "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. "
1432 "minImageCount = %d, maxImageCount = %d).",
1433 fn, pCreateInfo->minImageCount, pCapabilities->minImageCount, pCapabilities->maxImageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001434 }
1435 // Validate pCreateInfo->imageExtent against
1436 // VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
1437 if ((pCapabilities->currentExtent.width == -1) &&
1438 ((pCreateInfo->imageExtent.width < pCapabilities->minImageExtent.width) ||
1439 (pCreateInfo->imageExtent.width > pCapabilities->maxImageExtent.width) ||
1440 (pCreateInfo->imageExtent.height < pCapabilities->minImageExtent.height) ||
1441 (pCreateInfo->imageExtent.height > pCapabilities->maxImageExtent.height))) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001442 skipCall |= LOG_ERROR(
1443 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS,
1444 "%s() called with pCreateInfo->imageExtent = "
1445 "(%d,%d), which is outside the bounds "
1446 "returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): "
1447 "currentExtent = (%d,%d), minImageExtent = "
1448 "(%d,%d), maxImageExtent = (%d,%d).",
1449 fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, pCapabilities->currentExtent.width,
1450 pCapabilities->currentExtent.height, pCapabilities->minImageExtent.width, pCapabilities->minImageExtent.height,
1451 pCapabilities->maxImageExtent.width, pCapabilities->maxImageExtent.height);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001452 }
1453 if ((pCapabilities->currentExtent.width != -1) &&
1454 ((pCreateInfo->imageExtent.width != pCapabilities->currentExtent.width) ||
1455 (pCreateInfo->imageExtent.height != pCapabilities->currentExtent.height))) {
1456 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001457 SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN, "%s() called with pCreateInfo->imageExtent = "
1458 "(%d,%d), which is not equal to the "
1459 "currentExtent = (%d,%d) returned by "
1460 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1461 fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height,
1462 pCapabilities->currentExtent.width, pCapabilities->currentExtent.height);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001463 }
1464 // Validate pCreateInfo->preTransform has one bit set (1st two
1465 // lines of if-statement), which bit is also set in
1466 // VkSurfaceCapabilitiesKHR::supportedTransforms (3rd line of if-statement):
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001467 if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) ||
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001468 !(pCreateInfo->preTransform & pCapabilities->supportedTransforms)) {
1469 // This is an error situation; one for which we'd like to give
1470 // the developer a helpful, multi-line error message. Build it
1471 // up a little at a time, and then log it:
1472 std::string errorString = "";
1473 char str[1024];
1474 // Here's the first part of the message:
1475 sprintf(str, "%s() called with a non-supported "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001476 "pCreateInfo->preTransform (i.e. %s). "
1477 "Supported values are:\n",
1478 fn, surfaceTransformStr(pCreateInfo->preTransform));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001479 errorString += str;
1480 for (int i = 0; i < 32; i++) {
1481 // Build up the rest of the message:
1482 if ((1 << i) & pCapabilities->supportedTransforms) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001483 const char *newStr = surfaceTransformStr((VkSurfaceTransformFlagBitsKHR)(1 << i));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001484 sprintf(str, " %s\n", newStr);
1485 errorString += str;
1486 }
1487 }
1488 // Log the message that we've built up:
Mark Lobodzinskia4cbbcd2016-05-24 15:44:50 -06001489 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1490 reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM, LAYER_NAME,
1491 "%s", errorString.c_str());
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001492 }
1493 // Validate pCreateInfo->compositeAlpha has one bit set (1st two
1494 // lines of if-statement), which bit is also set in
1495 // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha (3rd line of if-statement):
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001496 if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) ||
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001497 !((pCreateInfo->compositeAlpha) & pCapabilities->supportedCompositeAlpha)) {
1498 // This is an error situation; one for which we'd like to give
1499 // the developer a helpful, multi-line error message. Build it
1500 // up a little at a time, and then log it:
1501 std::string errorString = "";
1502 char str[1024];
1503 // Here's the first part of the message:
1504 sprintf(str, "%s() called with a non-supported "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001505 "pCreateInfo->compositeAlpha (i.e. %s). "
1506 "Supported values are:\n",
1507 fn, surfaceCompositeAlphaStr(pCreateInfo->compositeAlpha));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001508 errorString += str;
1509 for (int i = 0; i < 32; i++) {
1510 // Build up the rest of the message:
1511 if ((1 << i) & pCapabilities->supportedCompositeAlpha) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001512 const char *newStr = surfaceCompositeAlphaStr((VkCompositeAlphaFlagBitsKHR)(1 << i));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001513 sprintf(str, " %s\n", newStr);
1514 errorString += str;
1515 }
1516 }
1517 // Log the message that we've built up:
Mark Lobodzinskia4cbbcd2016-05-24 15:44:50 -06001518 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1519 reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA,
1520 LAYER_NAME, "%s", errorString.c_str());
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001521 }
1522 // Validate pCreateInfo->imageArraySize against
1523 // VkSurfaceCapabilitiesKHR::maxImageArraySize:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001524 if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > pCapabilities->maxImageArrayLayers)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001525 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001526 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_SIZE, "%s() called with a non-supported "
1527 "pCreateInfo->imageArraySize (i.e. %d). "
1528 "Minimum value is 1, maximum value is %d.",
1529 fn, pCreateInfo->imageArrayLayers, pCapabilities->maxImageArrayLayers);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001530 }
1531 // Validate pCreateInfo->imageUsage against
1532 // VkSurfaceCapabilitiesKHR::supportedUsageFlags:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001533 if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & pCapabilities->supportedUsageFlags)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001534 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001535 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS, "%s() called with a non-supported "
1536 "pCreateInfo->imageUsage (i.e. 0x%08x)."
1537 " Supported flag bits are 0x%08x.",
1538 fn, pCreateInfo->imageUsage, pCapabilities->supportedUsageFlags);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001539 }
1540 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001541
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001542 // Validate pCreateInfo values with the results of
1543 // vkGetPhysicalDeviceSurfaceFormatsKHR():
1544 if (!pPhysicalDevice || !pPhysicalDevice->surfaceFormatCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001545 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001546 "%s() called before calling "
1547 "vkGetPhysicalDeviceSurfaceFormatsKHR().",
1548 fn);
1549 } else if (pCreateInfo) {
1550 // Validate pCreateInfo->imageFormat against
1551 // VkSurfaceFormatKHR::format:
1552 bool foundFormat = false;
1553 bool foundColorSpace = false;
1554 bool foundMatch = false;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001555 for (uint32_t i = 0; i < pPhysicalDevice->surfaceFormatCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001556 if (pCreateInfo->imageFormat == pPhysicalDevice->pSurfaceFormats[i].format) {
1557 // Validate pCreateInfo->imageColorSpace against
1558 // VkSurfaceFormatKHR::colorSpace:
1559 foundFormat = true;
1560 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1561 foundMatch = true;
1562 break;
1563 }
1564 } else {
1565 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1566 foundColorSpace = true;
1567 }
1568 }
1569 }
1570 if (!foundMatch) {
1571 if (!foundFormat) {
1572 if (!foundColorSpace) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001573 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1574 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP, "%s() called with neither a "
1575 "supported pCreateInfo->imageFormat "
1576 "(i.e. %d) nor a supported "
1577 "pCreateInfo->imageColorSpace "
1578 "(i.e. %d).",
1579 fn, pCreateInfo->imageFormat, pCreateInfo->imageColorSpace);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001580 } else {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001581 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1582 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT, "%s() called with a non-supported "
1583 "pCreateInfo->imageFormat (i.e. %d).",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001584 fn, pCreateInfo->imageFormat);
1585 }
1586 } else if (!foundColorSpace) {
1587 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001588 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE, "%s() called with a non-supported "
1589 "pCreateInfo->imageColorSpace (i.e. %d).",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001590 fn, pCreateInfo->imageColorSpace);
1591 }
1592 }
1593 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001594
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001595 // Validate pCreateInfo values with the results of
1596 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1597 if (!pPhysicalDevice || !pPhysicalDevice->presentModeCount) {
szdarkhackfb287d32016-03-12 18:41:19 +02001598 if (!pCreateInfo || (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR)) {
1599 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
1600 "%s() called before calling "
1601 "vkGetPhysicalDeviceSurfacePresentModesKHR().",
1602 fn);
1603 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001604 } else if (pCreateInfo) {
1605 // Validate pCreateInfo->presentMode against
1606 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1607 bool foundMatch = false;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001608 for (uint32_t i = 0; i < pPhysicalDevice->presentModeCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001609 if (pPhysicalDevice->pPresentModes[i] == pCreateInfo->presentMode) {
1610 foundMatch = true;
1611 break;
1612 }
1613 }
1614 if (!foundMatch) {
1615 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001616 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE, "%s() called with a non-supported "
1617 "pCreateInfo->presentMode (i.e. %s).",
1618 fn, presentModeStr(pCreateInfo->presentMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001619 }
1620 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001621
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001622 // Validate pCreateInfo->imageSharingMode and related values:
1623 if (pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001624 if ((pCreateInfo->queueFamilyIndexCount <= 1) || !pCreateInfo->pQueueFamilyIndices) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001625 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001626 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_VALUES, "%s() called with a supported "
baldurk209ccda2016-05-05 16:31:05 +02001627 "pCreateInfo->sharingMode of (i.e. %s), "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001628 "but with a bad value(s) for "
1629 "pCreateInfo->queueFamilyIndexCount or "
1630 "pCreateInfo->pQueueFamilyIndices).",
1631 fn, sharingModeStr(pCreateInfo->imageSharingMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001632 }
1633 } else if (pCreateInfo->imageSharingMode != VK_SHARING_MODE_EXCLUSIVE) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001634 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 -07001635 "%s() called with a non-supported "
1636 "pCreateInfo->imageSharingMode (i.e. %s).",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001637 fn, sharingModeStr(pCreateInfo->imageSharingMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001638 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001639
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001640 // Validate pCreateInfo->clipped:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001641 if (pCreateInfo && (pCreateInfo->clipped != VK_FALSE) && (pCreateInfo->clipped != VK_TRUE)) {
1642 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_BAD_BOOL,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001643 "%s() called with a VkBool32 value that is "
1644 "neither VK_TRUE nor VK_FALSE, but has the "
1645 "numeric value of %d.",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001646 fn, pCreateInfo->clipped);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001647 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001648
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001649 // Validate pCreateInfo->oldSwapchain:
1650 if (pCreateInfo && pCreateInfo->oldSwapchain) {
Ian Elliott77f46ca2016-05-05 14:10:49 -06001651 SwpSwapchain *pOldSwapchain = NULL;
1652 {
1653 auto it = my_data->swapchainMap.find(pCreateInfo->oldSwapchain);
1654 pOldSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1655 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001656 if (pOldSwapchain) {
1657 if (device != pOldSwapchain->pDevice->device) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001658 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1659 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE, "%s() called with a different VkDevice "
1660 "than the VkSwapchainKHR was created with.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001661 __FUNCTION__);
1662 }
1663 if (pCreateInfo->surface != pOldSwapchain->pSurface->surface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001664 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1665 SWAPCHAIN_CREATE_SWAP_DIFF_SURFACE, "%s() called with pCreateInfo->oldSwapchain "
1666 "that has a different VkSurfaceKHR than "
1667 "pCreateInfo->surface.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001668 fn);
1669 }
1670 } else {
1671 // TBD: Leave this in (not sure object_track will check this)?
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001672 skipCall |=
1673 LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pCreateInfo->oldSwapchain, "VkSwapchainKHR");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001674 }
1675 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001676
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001677 return skipCall;
1678}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001679
Chia-I Wufccbfe42016-04-28 14:01:30 +08001680VKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
1681 const VkAllocationCallbacks *pAllocator,
1682 VkSwapchainKHR *pSwapchain) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001683 VkResult result = VK_SUCCESS;
1684 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001685 std::unique_lock<std::mutex> lock(global_lock);
Dustin Graves080069b2016-04-05 13:48:15 -06001686 bool skipCall = validateCreateSwapchainKHR(device, pCreateInfo, pSwapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001687
Dustin Graves080069b2016-04-05 13:48:15 -06001688 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001689 // Call down the call chain:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001690 lock.unlock();
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001691 result = my_data->device_dispatch_table->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001692 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001693
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001694 if (result == VK_SUCCESS) {
1695 // Remember the swapchain's handle, and link it to the device:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001696 SwpDevice *pDevice = NULL;
1697 {
1698 auto it = my_data->deviceMap.find(device);
1699 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1700 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001701
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001702 my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
1703 if (pDevice) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001704 pDevice->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001705 }
1706 my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
1707 my_data->swapchainMap[*pSwapchain].imageCount = 0;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001708 my_data->swapchainMap[*pSwapchain].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001709 // Store a pointer to the surface
1710 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001711 SwpInstance *pInstance = (pPhysicalDevice) ? pPhysicalDevice->pInstance : NULL;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001712 layer_data *my_instance_data =
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001713 ((pInstance) ? get_my_data_ptr(get_dispatch_key(pInstance->instance), layer_data_map) : NULL);
1714 SwpSurface *pSurface = ((my_data && pCreateInfo) ? &my_instance_data->surfaceMap[pCreateInfo->surface] : NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001715 my_data->swapchainMap[*pSwapchain].pSurface = pSurface;
1716 if (pSurface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001717 pSurface->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001718 }
1719 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001720 return result;
1721 }
1722 return VK_ERROR_VALIDATION_FAILED_EXT;
1723}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001724
Chia-I Wufccbfe42016-04-28 14:01:30 +08001725VKAPI_ATTR void VKAPI_CALL
1726DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001727 // TODOs:
1728 //
1729 // - Implement a check for validity language that reads: All uses of
Ian Elliotta5d13a92016-04-07 09:05:45 -06001730 // presentable images acquired from pname:swapchain must: have completed
1731 // execution
Dustin Graves080069b2016-04-05 13:48:15 -06001732 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001733 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001734 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001735 SwpDevice *pDevice = NULL;
1736 {
1737 auto it = my_data->deviceMap.find(device);
1738 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1739 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07001740
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001741 // Validate that the swapchain extension was enabled:
1742 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001743 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1744 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
1745 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001746 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001747
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001748 // Regardless of skipCall value, do some internal cleanup:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001749 SwpSwapchain *pSwapchain = NULL;
1750 {
1751 auto it = my_data->swapchainMap.find(swapchain);
1752 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1753 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001754 if (pSwapchain) {
1755 // Delete the SwpSwapchain associated with this swapchain:
1756 if (pSwapchain->pDevice) {
1757 pSwapchain->pDevice->swapchains.erase(swapchain);
1758 if (device != pSwapchain->pDevice->device) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001759 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001760 "%s() called with a different VkDevice than the "
1761 "VkSwapchainKHR was created with.",
1762 __FUNCTION__);
1763 }
1764 }
1765 if (pSwapchain->pSurface) {
1766 pSwapchain->pSurface->swapchains.erase(swapchain);
1767 }
1768 if (pSwapchain->imageCount) {
1769 pSwapchain->images.clear();
1770 }
1771 if ((pAllocator != NULL) != pSwapchain->usedAllocatorToCreate) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001772 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001773 "%s() called with incompatible pAllocator from when "
1774 "the object was created.",
1775 __FUNCTION__);
1776 }
1777 my_data->swapchainMap.erase(swapchain);
1778 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001779 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001780
Dustin Graves080069b2016-04-05 13:48:15 -06001781 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001782 // Call down the call chain:
1783 my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator);
1784 }
1785}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001786
Chia-I Wufccbfe42016-04-28 14:01:30 +08001787VKAPI_ATTR VkResult VKAPI_CALL
1788GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001789 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001790 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001791 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001792 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001793 SwpDevice *pDevice = NULL;
1794 {
1795 auto it = my_data->deviceMap.find(device);
1796 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1797 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07001798
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001799 // Validate that the swapchain extension was enabled:
1800 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001801 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1802 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
1803 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001804 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06001805 SwpSwapchain *pSwapchain = NULL;
1806 {
1807 auto it = my_data->swapchainMap.find(swapchain);
1808 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1809 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001810 if (!pSwapchainImageCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001811 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchainImageCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001812 } else if (pSwapchain && pSwapchainImages) {
1813 // Compare the preliminary value of *pSwapchainImageCount with the
1814 // value this time:
1815 if (pSwapchain->imageCount == 0) {
1816 // Since we haven't recorded a preliminary value of
1817 // *pSwapchainImageCount, that likely means that the application
1818 // didn't previously call this function with a NULL value of
1819 // pSwapchainImages:
1820 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
1821 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1822 device, "pSwapchainImageCount", "pSwapchainImages");
1823 } else if (*pSwapchainImageCount > pSwapchain->imageCount) {
1824 skipCall |= LOG_ERROR_INVALID_COUNT(
1825 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1826 device, "pSwapchainImageCount", "pSwapchainImages",
1827 *pSwapchainImageCount, pSwapchain->imageCount);
1828 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001829 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001830
Dustin Graves080069b2016-04-05 13:48:15 -06001831 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001832 // Call down the call chain:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001833 lock.unlock();
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001834 result = my_data->device_dispatch_table->GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001835 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001836
Ian Elliott32311832016-02-04 08:17:18 -07001837 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001838 {
1839 auto it = my_data->swapchainMap.find(swapchain);
1840 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1841 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001842 if ((result == VK_SUCCESS) && pSwapchain && !pSwapchainImages && pSwapchainImageCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001843 // Record the result of this preliminary query:
1844 pSwapchain->imageCount = *pSwapchainImageCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001845 } else if ((result == VK_SUCCESS) && pSwapchain && pSwapchainImages &&
1846 pSwapchainImageCount && (*pSwapchainImageCount > 0)) {
1847 // Record the images and their state:
1848 pSwapchain->imageCount = *pSwapchainImageCount;
1849 for (uint32_t i = 0; i < *pSwapchainImageCount; i++) {
1850 pSwapchain->images[i].image = pSwapchainImages[i];
1851 pSwapchain->images[i].pSwapchain = pSwapchain;
1852 pSwapchain->images[i].acquiredByApp = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001853 }
1854 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001855 return result;
1856 }
1857 return VK_ERROR_VALIDATION_FAILED_EXT;
1858}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001859
Chia-I Wufccbfe42016-04-28 14:01:30 +08001860VKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
1861 VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001862 // TODOs:
1863 //
1864 // - Address the timeout. Possibilities include looking at the state of the
1865 // swapchain's images, depending on the timeout value.
1866 // - Implement a check for validity language that reads: If pname:semaphore is
1867 // not sname:VK_NULL_HANDLE it must: be unsignalled
1868 // - Implement a check for validity language that reads: If pname:fence is not
1869 // sname:VK_NULL_HANDLE it must: be unsignalled and mustnot: be associated
1870 // with any other queue command that has not yet completed execution on that
1871 // queue
1872 // - Record/update the state of the swapchain, in case an error occurs
1873 // (e.g. VK_ERROR_OUT_OF_DATE_KHR).
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001874 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001875 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001876 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001877 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001878 SwpDevice *pDevice = NULL;
1879 {
1880 auto it = my_data->deviceMap.find(device);
1881 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1882 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07001883
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001884 // Validate that the swapchain extension was enabled:
1885 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001886 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1887 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
1888 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001889 }
Ian Elliottfa8f0322016-03-23 08:28:54 -06001890 if ((semaphore == VK_NULL_HANDLE) && (fence == VK_NULL_HANDLE)) {
Ian Elliott5da0c962016-03-23 11:13:09 -06001891 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_NO_SYNC_FOR_ACQUIRE,
1892 "%s() called with both the semaphore and fence parameters set to "
Jamie Madillcc4e9322016-05-04 12:20:15 -07001893 "VK_NULL_HANDLE (at least one should be used).", __FUNCTION__);
Ian Elliottfa8f0322016-03-23 08:28:54 -06001894 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06001895 SwpSwapchain *pSwapchain = NULL;
1896 {
1897 auto it = my_data->swapchainMap.find(swapchain);
1898 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1899 }
Ian Elliott5c680282016-04-06 14:29:56 -06001900 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
1901 if (pSwapchain && pPhysicalDevice && pPhysicalDevice->gotSurfaceCapabilities) {
1902 // Look to see if the application has already acquired the maximum
1903 // number of images, and this will push it past the spec-defined
1904 // limits:
1905 uint32_t minImageCount = pPhysicalDevice->surfaceCapabilities.minImageCount;
1906 uint32_t imagesAcquiredByApp = 0;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001907 for (uint32_t i = 0; i < pSwapchain->imageCount; i++) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06001908 if (pSwapchain->images[i].acquiredByApp) {
Ian Elliott5c680282016-04-06 14:29:56 -06001909 imagesAcquiredByApp++;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001910 }
1911 }
Ian Elliott5c680282016-04-06 14:29:56 -06001912 if (imagesAcquiredByApp > (pSwapchain->imageCount - minImageCount)) {
1913 skipCall |= LOG_ERROR(
1914 VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
1915 swapchain, "VkSwapchainKHR",
1916 SWAPCHAIN_APP_ACQUIRES_TOO_MANY_IMAGES,
1917 "%s() called when it cannot succeed. The application has "
1918 "acquired %d image(s) that have not yet been presented. The "
1919 "maximum number of images that the application can "
1920 "simultaneously acquire from this swapchain (including this "
1921 "call to %s()) is %d. That value is derived by subtracting "
1922 "VkSurfaceCapabilitiesKHR::minImageCount (%d) from the number "
1923 "of images in the swapchain (%d) and adding 1.\n",
1924 __FUNCTION__, imagesAcquiredByApp, __FUNCTION__,
1925 (pSwapchain->imageCount - minImageCount + 1),
1926 minImageCount, pSwapchain->imageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001927 }
1928 }
1929 if (!pImageIndex) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001930 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pImageIndex");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001931 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001932
Dustin Graves080069b2016-04-05 13:48:15 -06001933 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001934 // Call down the call chain:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001935 lock.unlock();
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001936 result = my_data->device_dispatch_table->AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001937 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001938
Ian Elliott32311832016-02-04 08:17:18 -07001939 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001940 {
1941 auto it = my_data->swapchainMap.find(swapchain);
1942 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1943 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001944 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) && pSwapchain) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06001945 // Change the state of the image (now acquired by the application):
1946 pSwapchain->images[*pImageIndex].acquiredByApp = true;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001947 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001948 return result;
1949 }
1950 return VK_ERROR_VALIDATION_FAILED_EXT;
1951}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001952
Chia-I Wufccbfe42016-04-28 14:01:30 +08001953VKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001954 // TODOs:
1955 //
1956 // - Implement a check for validity language that reads: Any given element of
1957 // sname:VkSemaphore in pname:pWaitSemaphores must: refer to a prior signal
1958 // of that sname:VkSemaphore that won't be consumed by any other wait on that
1959 // semaphore
1960 // - Record/update the state of the swapchain, in case an error occurs
1961 // (e.g. VK_ERROR_OUT_OF_DATE_KHR).
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001962 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001963 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001964 layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001965
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001966 if (!pPresentInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001967 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001968 } else {
1969 if (pPresentInfo->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001970 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001971 "VK_STRUCTURE_TYPE_PRESENT_INFO_KHR");
1972 }
1973 if (pPresentInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001974 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001975 }
1976 if (!pPresentInfo->swapchainCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001977 skipCall |= LOG_ERROR_ZERO_VALUE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->swapchainCount");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001978 }
1979 if (!pPresentInfo->pSwapchains) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001980 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pSwapchains");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001981 }
1982 if (!pPresentInfo->pImageIndices) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001983 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pImageIndices");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001984 }
1985 // Note: pPresentInfo->pResults is allowed to be NULL
1986 }
Ian Elliott046ed2c2015-12-30 17:07:17 -07001987
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001988 std::unique_lock<std::mutex> lock(global_lock);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001989 for (uint32_t i = 0; pPresentInfo && (i < pPresentInfo->swapchainCount); i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001990 uint32_t index = pPresentInfo->pImageIndices[i];
Ian Elliott77f46ca2016-05-05 14:10:49 -06001991 SwpSwapchain *pSwapchain = NULL;
1992 {
1993 auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
1994 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1995 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001996 if (pSwapchain) {
1997 if (!pSwapchain->pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001998 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, pSwapchain->pDevice, "VkDevice",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001999 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002000 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2001 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002002 }
2003 if (index >= pSwapchain->imageCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002004 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
2005 SWAPCHAIN_INDEX_TOO_LARGE, "%s() called for an index that is too "
2006 "large (i.e. %d). There are only %d "
2007 "images in this VkSwapchainKHR.\n",
2008 __FUNCTION__, index, pSwapchain->imageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002009 } else {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002010 if (!pSwapchain->images[index].acquiredByApp) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002011 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i],
2012 "VkSwapchainKHR", SWAPCHAIN_INDEX_NOT_IN_USE, "%s() returned an index (i.e. %d) "
Ian Elliotta5d13a92016-04-07 09:05:45 -06002013 "for an image that is not acquired by "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002014 "the application.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002015 __FUNCTION__, index);
2016 }
2017 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06002018 SwpQueue *pQueue = NULL;
2019 {
2020 auto it = my_data->queueMap.find(queue);
2021 pQueue = (it == my_data->queueMap.end()) ? NULL : &it->second;
2022 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002023 SwpSurface *pSurface = pSwapchain->pSurface;
2024 if (pQueue && pSurface && pSurface->numQueueFamilyIndexSupport) {
2025 uint32_t queueFamilyIndex = pQueue->queueFamilyIndex;
2026 // Note: the 1st test is to ensure queueFamilyIndex is in range,
2027 // and the 2nd test is the validation check:
2028 if ((pSurface->numQueueFamilyIndexSupport > queueFamilyIndex) &&
2029 (!pSurface->pQueueFamilyIndexSupport[queueFamilyIndex])) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002030 skipCall |=
2031 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
2032 SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, "%s() called with a swapchain whose "
2033 "surface is not supported for "
2034 "presention on this device with the "
2035 "queueFamilyIndex (i.e. %d) of the "
2036 "given queue.",
2037 __FUNCTION__, queueFamilyIndex);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002038 }
2039 }
2040 }
2041 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002042
Dustin Graves080069b2016-04-05 13:48:15 -06002043 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002044 // Call down the call chain:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002045 lock.unlock();
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002046 result = my_data->device_dispatch_table->QueuePresentKHR(queue, pPresentInfo);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002047 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002048
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002049 if (pPresentInfo && ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR))) {
2050 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002051 int index = pPresentInfo->pImageIndices[i];
Ian Elliott77f46ca2016-05-05 14:10:49 -06002052 SwpSwapchain *pSwapchain = NULL;
2053 {
2054 auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
2055 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2056 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002057 if (pSwapchain) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002058 // Change the state of the image (no longer acquired by the
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002059 // application):
Ian Elliotta5d13a92016-04-07 09:05:45 -06002060 pSwapchain->images[index].acquiredByApp = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002061 }
2062 }
2063 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002064 return result;
2065 }
2066 return VK_ERROR_VALIDATION_FAILED_EXT;
2067}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002068
Chia-I Wufccbfe42016-04-28 14:01:30 +08002069VKAPI_ATTR void VKAPI_CALL
2070GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
Dustin Graves080069b2016-04-05 13:48:15 -06002071 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002072 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliottc4db6952016-01-21 14:29:45 -07002073
Dustin Graves080069b2016-04-05 13:48:15 -06002074 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002075 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002076 my_data->device_dispatch_table->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
Ian Elliottc4db6952016-01-21 14:29:45 -07002077
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002078 // Remember the queue's handle, and link it to the device:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002079 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002080 SwpDevice *pDevice = NULL;
2081 {
2082 auto it = my_data->deviceMap.find(device);
2083 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2084 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002085 my_data->queueMap[&pQueue].queue = *pQueue;
2086 if (pDevice) {
2087 pDevice->queues[*pQueue] = &my_data->queueMap[*pQueue];
2088 }
2089 my_data->queueMap[&pQueue].pDevice = pDevice;
2090 my_data->queueMap[&pQueue].queueFamilyIndex = queueFamilyIndex;
2091 }
2092}
Ian Elliottc4db6952016-01-21 14:29:45 -07002093
Chia-I Wufccbfe42016-04-28 14:01:30 +08002094VKAPI_ATTR VkResult VKAPI_CALL
2095CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2096 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002097 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002098 VkResult result =
2099 my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002100 if (VK_SUCCESS == result) {
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002101 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -06002102 result = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002103 }
2104 return result;
2105}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002106
Chia-I Wufccbfe42016-04-28 14:01:30 +08002107VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance,
2108 VkDebugReportCallbackEXT msgCallback,
2109 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002110 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2111 my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002112 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002113 layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
2114}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002115
Chia-I Wufccbfe42016-04-28 14:01:30 +08002116VKAPI_ATTR void VKAPI_CALL
2117DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
2118 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002119 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002120 my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix,
2121 pMsg);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002122}
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07002123
Chia-I Wub02600c2016-05-20 07:11:22 +08002124VKAPI_ATTR VkResult VKAPI_CALL
2125EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
2126 return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
2127}
2128
2129VKAPI_ATTR VkResult VKAPI_CALL
2130EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
2131 return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
2132}
2133
2134VKAPI_ATTR VkResult VKAPI_CALL
2135EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
2136 if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
2137 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
2138
2139 return VK_ERROR_LAYER_NOT_PRESENT;
2140}
2141
Chia-I Wufccbfe42016-04-28 14:01:30 +08002142VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
2143 const char *pLayerName, uint32_t *pCount,
2144 VkExtensionProperties *pProperties) {
Chia-I Wu2b481252016-04-28 14:21:13 +08002145 if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
Chia-I Wu045209e2016-04-28 11:21:49 +08002146 return util_GetExtensionProperties(0, nullptr, pCount, pProperties);
Chia-I Wu2b481252016-04-28 14:21:13 +08002147
2148 assert(physicalDevice);
2149
2150 dispatch_key key = get_dispatch_key(physicalDevice);
2151 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
2152 return my_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002153}
2154
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002155static PFN_vkVoidFunction
Chia-I Wu22813c72016-04-28 14:38:57 +08002156intercept_core_instance_command(const char *name);
2157
2158static PFN_vkVoidFunction
2159intercept_khr_surface_command(const char *name, VkInstance instance);
2160
2161static PFN_vkVoidFunction
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002162intercept_core_device_command(const char *name);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002163
Chia-I Wu83245952016-05-05 16:13:19 +08002164static PFN_vkVoidFunction
2165intercept_khr_swapchain_command(const char *name, VkDevice dev);
2166
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002167VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
2168 PFN_vkVoidFunction proc = intercept_core_device_command(funcName);
2169 if (proc)
2170 return proc;
2171
2172 assert(device);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002173
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002174 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06002175
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002176 my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Courtney Goeltzenleuchter1e9e6c82016-03-19 10:38:52 -06002177 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
Chia-I Wu83245952016-05-05 16:13:19 +08002178
2179 proc = intercept_khr_swapchain_command(funcName, device);
2180 if (proc)
2181 return proc;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002182
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002183 if (pDisp->GetDeviceProcAddr == NULL)
2184 return NULL;
2185 return pDisp->GetDeviceProcAddr(device, funcName);
2186}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002187
Chia-I Wufccbfe42016-04-28 14:01:30 +08002188VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wu22813c72016-04-28 14:38:57 +08002189 PFN_vkVoidFunction proc = intercept_core_instance_command(funcName);
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002190 if (!proc)
2191 proc = intercept_core_device_command(funcName);
2192 if (!proc)
2193 proc = intercept_khr_swapchain_command(funcName, VK_NULL_HANDLE);
Chia-I Wu22813c72016-04-28 14:38:57 +08002194 if (proc)
2195 return proc;
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07002196
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002197 assert(instance);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002198
2199 layer_data *my_data;
2200 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002201 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Ian Elliott68124ac2015-10-07 16:18:35 -06002202
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002203 proc = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
2204 if (!proc)
2205 proc = intercept_khr_surface_command(funcName, instance);
Chia-I Wu22813c72016-04-28 14:38:57 +08002206 if (proc)
2207 return proc;
Ian Elliott0b4d6242015-09-22 10:51:24 -06002208
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002209 if (pTable->GetInstanceProcAddr == NULL)
2210 return NULL;
2211 return pTable->GetInstanceProcAddr(instance, funcName);
2212}
Chia-I Wu045209e2016-04-28 11:21:49 +08002213
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002214static PFN_vkVoidFunction
Chia-I Wu22813c72016-04-28 14:38:57 +08002215intercept_core_instance_command(const char *name) {
2216 static const struct {
2217 const char *name;
2218 PFN_vkVoidFunction proc;
2219 } core_instance_commands[] = {
2220 { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
2221 { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
2222 { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) },
2223 { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
2224 { "vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices) },
Chia-I Wub02600c2016-05-20 07:11:22 +08002225 { "vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties) },
2226 { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
2227 { "vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties) },
Chia-I Wu22813c72016-04-28 14:38:57 +08002228 { "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
2229 { "vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties) },
2230 };
2231
2232 for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
2233 if (!strcmp(core_instance_commands[i].name, name))
2234 return core_instance_commands[i].proc;
2235 }
2236
2237 return nullptr;
2238}
2239
2240static PFN_vkVoidFunction
2241intercept_khr_surface_command(const char *name, VkInstance instance) {
2242 static const struct {
2243 const char *name;
2244 PFN_vkVoidFunction proc;
2245 } khr_surface_commands[] = {
2246#ifdef VK_USE_PLATFORM_ANDROID_KHR
2247 { "vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateAndroidSurfaceKHR) },
2248#endif // VK_USE_PLATFORM_ANDROID_KHR
2249#ifdef VK_USE_PLATFORM_MIR_KHR
2250 { "vkCreateMirSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateMirSurfaceKHR) },
2251 { "vkGetPhysicalDeviceMirPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceMirPresentationSupportKHR) },
2252#endif // VK_USE_PLATFORM_MIR_KHR
2253#ifdef VK_USE_PLATFORM_WAYLAND_KHR
2254 { "vkCreateWaylandSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWaylandSurfaceKHR) },
2255 { "vkGetPhysicalDeviceWaylandPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWaylandPresentationSupportKHR) },
2256#endif // VK_USE_PLATFORM_WAYLAND_KHR
2257#ifdef VK_USE_PLATFORM_WIN32_KHR
2258 { "vkCreateWin32SurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWin32SurfaceKHR) },
2259 { "vkGetPhysicalDeviceWin32PresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWin32PresentationSupportKHR) },
2260#endif // VK_USE_PLATFORM_WIN32_KHR
2261#ifdef VK_USE_PLATFORM_XCB_KHR
2262 { "vkCreateXcbSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXcbSurfaceKHR) },
2263 { "vkGetPhysicalDeviceXcbPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXcbPresentationSupportKHR) },
2264#endif // VK_USE_PLATFORM_XCB_KHR
2265#ifdef VK_USE_PLATFORM_XLIB_KHR
2266 { "vkCreateXlibSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXlibSurfaceKHR) },
2267 { "vkGetPhysicalDeviceXlibPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXlibPresentationSupportKHR) },
2268#endif // VK_USE_PLATFORM_XLIB_KHR
2269 { "vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySurfaceKHR) },
2270 { "vkGetPhysicalDeviceSurfaceSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceSupportKHR) },
2271 { "vkGetPhysicalDeviceSurfaceCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceCapabilitiesKHR) },
2272 { "vkGetPhysicalDeviceSurfaceFormatsKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceFormatsKHR) },
2273 { "vkGetPhysicalDeviceSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfacePresentModesKHR) },
2274 };
2275
2276 // do not check if VK_KHR_*_surface is enabled (why?)
2277
2278 for (size_t i = 0; i < ARRAY_SIZE(khr_surface_commands); i++) {
2279 if (!strcmp(khr_surface_commands[i].name, name))
2280 return khr_surface_commands[i].proc;
2281 }
2282
2283 return nullptr;
2284}
2285
2286static PFN_vkVoidFunction
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002287intercept_core_device_command(const char *name) {
2288 static const struct {
2289 const char *name;
2290 PFN_vkVoidFunction proc;
2291 } core_device_commands[] = {
2292 { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
2293 { "vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice) },
2294 { "vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue) },
2295 };
2296
2297 for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) {
2298 if (!strcmp(core_device_commands[i].name, name))
2299 return core_device_commands[i].proc;
2300 }
2301
2302 return nullptr;
2303}
2304
Chia-I Wu83245952016-05-05 16:13:19 +08002305static PFN_vkVoidFunction
2306intercept_khr_swapchain_command(const char *name, VkDevice dev) {
2307 static const struct {
2308 const char *name;
2309 PFN_vkVoidFunction proc;
2310 } khr_swapchain_commands[] = {
2311 { "vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR) },
2312 { "vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR) },
2313 { "vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR) },
2314 { "vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR) },
2315 { "vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR) },
2316 };
2317
2318 // do not check if VK_KHR_swapchain is enabled (why?)
2319
2320 for (size_t i = 0; i < ARRAY_SIZE(khr_swapchain_commands); i++) {
2321 if (!strcmp(khr_swapchain_commands[i].name, name))
2322 return khr_swapchain_commands[i].proc;
2323 }
2324
2325 return nullptr;
2326}
2327
Chia-I Wu516b5082016-04-28 11:27:46 +08002328} // namespace swapchain
2329
2330// vk_layer_logging.h expects these to be defined
2331
Chia-I Wufccbfe42016-04-28 14:01:30 +08002332VKAPI_ATTR VkResult VKAPI_CALL
Chia-I Wu516b5082016-04-28 11:27:46 +08002333vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2334 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002335 return swapchain::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Chia-I Wu516b5082016-04-28 11:27:46 +08002336}
2337
Chia-I Wufccbfe42016-04-28 14:01:30 +08002338VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance,
Chia-I Wu516b5082016-04-28 11:27:46 +08002339 VkDebugReportCallbackEXT msgCallback,
2340 const VkAllocationCallbacks *pAllocator) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002341 swapchain::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Chia-I Wu516b5082016-04-28 11:27:46 +08002342}
2343
Chia-I Wufccbfe42016-04-28 14:01:30 +08002344VKAPI_ATTR void VKAPI_CALL
Chia-I Wu516b5082016-04-28 11:27:46 +08002345vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
2346 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002347 swapchain::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
Chia-I Wu516b5082016-04-28 11:27:46 +08002348}
2349
Chia-I Wub02600c2016-05-20 07:11:22 +08002350// loader-layer interface v0, just wrappers since there is only a layer
Chia-I Wu516b5082016-04-28 11:27:46 +08002351
Chia-I Wu045209e2016-04-28 11:21:49 +08002352VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2353vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002354 return swapchain::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002355}
2356
2357VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2358vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002359 return swapchain::EnumerateInstanceLayerProperties(pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002360}
2361
2362VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2363vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002364 // the layer command handles VK_NULL_HANDLE just fine internally
2365 assert(physicalDevice == VK_NULL_HANDLE);
2366 return swapchain::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
Chia-I Wu516b5082016-04-28 11:27:46 +08002367}
2368
2369VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
2370 const char *pLayerName, uint32_t *pCount,
2371 VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002372 // the layer command handles VK_NULL_HANDLE just fine internally
2373 assert(physicalDevice == VK_NULL_HANDLE);
Chia-I Wu2b481252016-04-28 14:21:13 +08002374 return swapchain::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
Chia-I Wu516b5082016-04-28 11:27:46 +08002375}
2376
2377VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002378 return swapchain::GetDeviceProcAddr(dev, funcName);
Chia-I Wu516b5082016-04-28 11:27:46 +08002379}
2380
2381VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002382 return swapchain::GetInstanceProcAddr(instance, funcName);
Chia-I Wu045209e2016-04-28 11:21:49 +08002383}