blob: f120c7a197d596153e22b04af3da1ee6edaefcc7 [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");
Petros Bantolas2b40be72016-04-15 11:02:59 +0100132 pDisp->CreateDisplayPlaneSurfaceKHR =
133 (PFN_vkCreateDisplayPlaneSurfaceKHR)gpa(instance, "vkCreateDisplayPlaneSurfaceKHR");
134 pDisp->GetPhysicalDeviceDisplayPropertiesKHR =
135 (PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)gpa(instance, "vkGetPhysicalDeviceDisplayPropertiesKHR");
136 pDisp->GetPhysicalDeviceDisplayPlanePropertiesKHR =
137 (PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)gpa(instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR");
138 pDisp->GetDisplayPlaneSupportedDisplaysKHR =
139 (PFN_vkGetDisplayPlaneSupportedDisplaysKHR)gpa(instance, "vkGetDisplayPlaneSupportedDisplaysKHR");
140 pDisp->GetDisplayModePropertiesKHR =
141 (PFN_vkGetDisplayModePropertiesKHR)gpa(instance, "vkGetDisplayModePropertiesKHR");
142 pDisp->CreateDisplayModeKHR =
143 (PFN_vkCreateDisplayModeKHR)gpa(instance, "vkCreateDisplayModeKHR");
144 pDisp->GetDisplayPlaneCapabilitiesKHR =
145 (PFN_vkGetDisplayPlaneCapabilitiesKHR)gpa(instance, "vkGetDisplayPlaneCapabilitiesKHR");
Ian Elliott0b4d6242015-09-22 10:51:24 -0600146
Ian Elliott1dcd1092015-11-17 17:29:40 -0700147 // Remember this instance, and whether the VK_KHR_surface extension
Ian Elliott0b4d6242015-09-22 10:51:24 -0600148 // was enabled for it:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600149 my_data->instanceMap[instance].instance = instance;
Ian Elliott1cb77a62015-12-29 16:44:39 -0700150 my_data->instanceMap[instance].surfaceExtensionEnabled = false;
Petros Bantolas2b40be72016-04-15 11:02:59 +0100151 my_data->instanceMap[instance].displayExtensionEnabled = false;
Ian Elliott8dffaf32016-01-04 14:10:30 -0700152#ifdef VK_USE_PLATFORM_ANDROID_KHR
153 my_data->instanceMap[instance].androidSurfaceExtensionEnabled = false;
154#endif // VK_USE_PLATFORM_ANDROID_KHR
155#ifdef VK_USE_PLATFORM_MIR_KHR
156 my_data->instanceMap[instance].mirSurfaceExtensionEnabled = false;
157#endif // VK_USE_PLATFORM_MIR_KHR
158#ifdef VK_USE_PLATFORM_WAYLAND_KHR
159 my_data->instanceMap[instance].waylandSurfaceExtensionEnabled = false;
160#endif // VK_USE_PLATFORM_WAYLAND_KHR
161#ifdef VK_USE_PLATFORM_WIN32_KHR
162 my_data->instanceMap[instance].win32SurfaceExtensionEnabled = false;
163#endif // VK_USE_PLATFORM_WIN32_KHR
164#ifdef VK_USE_PLATFORM_XCB_KHR
165 my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = false;
166#endif // VK_USE_PLATFORM_XCB_KHR
167#ifdef VK_USE_PLATFORM_XLIB_KHR
168 my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = false;
169#endif // VK_USE_PLATFORM_XLIB_KHR
170
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600171 // Look for one or more debug report create info structures, and copy the
172 // callback(s) for each one found (for use by vkDestroyInstance)
173 layer_copy_tmp_callbacks(pCreateInfo->pNext, &my_data->num_tmp_callbacks, &my_data->tmp_dbg_create_infos,
174 &my_data->tmp_callbacks);
175
Ian Elliott0b4d6242015-09-22 10:51:24 -0600176 // Record whether the WSI instance extension was enabled for this
177 // VkInstance. No need to check if the extension was advertised by
178 // vkEnumerateInstanceExtensionProperties(), since the loader handles that.
Jon Ashburnf19916e2016-01-11 13:12:43 -0700179 for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700180 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600181
Ian Elliott1cb77a62015-12-29 16:44:39 -0700182 my_data->instanceMap[instance].surfaceExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600183 }
Petros Bantolas2b40be72016-04-15 11:02:59 +0100184 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_DISPLAY_EXTENSION_NAME) == 0) {
185
186 my_data->instanceMap[instance].displayExtensionEnabled = true;
187 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700188#ifdef VK_USE_PLATFORM_ANDROID_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700189 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700190
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700191 my_data->instanceMap[instance].androidSurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800192 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700193#endif // VK_USE_PLATFORM_ANDROID_KHR
194#ifdef VK_USE_PLATFORM_MIR_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700195 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_MIR_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700196
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700197 my_data->instanceMap[instance].mirSurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800198 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700199#endif // VK_USE_PLATFORM_MIR_KHR
200#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700201 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700202
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700203 my_data->instanceMap[instance].waylandSurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800204 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700205#endif // VK_USE_PLATFORM_WAYLAND_KHR
206#ifdef VK_USE_PLATFORM_WIN32_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700207 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700208
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700209 my_data->instanceMap[instance].win32SurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800210 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700211#endif // VK_USE_PLATFORM_WIN32_KHR
212#ifdef VK_USE_PLATFORM_XCB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700213 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700214
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700215 my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = true;
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800216 }
Ian Elliott8dffaf32016-01-04 14:10:30 -0700217#endif // VK_USE_PLATFORM_XCB_KHR
218#ifdef VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700219 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott8dffaf32016-01-04 14:10:30 -0700220
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700221 my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = true;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700222 }
Jason Ekstranda5ebe8a2016-02-12 17:25:03 -0800223#endif // VK_USE_PLATFORM_XLIB_KHR
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700224 }
225}
226
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700227#include "vk_dispatch_table_helper.h"
Mark Lobodzinski1079e1b2016-03-15 14:21:59 -0600228static void init_swapchain(layer_data *my_data, const VkAllocationCallbacks *pAllocator) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600229
Mark Lobodzinski1079e1b2016-03-15 14:21:59 -0600230 layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_swapchain");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700231}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600232
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700233static const char *surfaceTransformStr(VkSurfaceTransformFlagBitsKHR value) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700234 // Return a string corresponding to the value:
235 return string_VkSurfaceTransformFlagBitsKHR(value);
236}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600237
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700238static const char *surfaceCompositeAlphaStr(VkCompositeAlphaFlagBitsKHR value) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700239 // Return a string corresponding to the value:
240 return string_VkCompositeAlphaFlagBitsKHR(value);
241}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600242
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700243static const char *presentModeStr(VkPresentModeKHR value) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700244 // Return a string corresponding to the value:
245 return string_VkPresentModeKHR(value);
246}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600247
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700248static const char *sharingModeStr(VkSharingMode value) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700249 // Return a string corresponding to the value:
250 return string_VkSharingMode(value);
251}
Ian Elliott07adb112016-01-05 12:51:03 -0700252
Chia-I Wufccbfe42016-04-28 14:01:30 +0800253VKAPI_ATTR VkResult VKAPI_CALL
254CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700255 VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600256
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700257 assert(chain_info->u.pLayerInfo);
258 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700259 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700260 if (fpCreateInstance == NULL) {
261 return VK_ERROR_INITIALIZATION_FAILED;
262 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700263
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700264 // Advance the link info for the next element on the chain
265 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700266
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700267 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
268 if (result != VK_SUCCESS) {
269 return result;
270 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700271
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700272 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
Chia-I Wua6737532016-04-28 16:04:15 +0800273 my_data->instance = *pInstance;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700274 my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
275 layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700276
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700277 my_data->report_data = debug_report_create_instance(my_data->instance_dispatch_table, *pInstance,
278 pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700279
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700280 // Call the following function after my_data is initialized:
281 createInstanceRegisterExtensions(pCreateInfo, *pInstance);
Mark Lobodzinski1079e1b2016-03-15 14:21:59 -0600282 init_swapchain(my_data, pAllocator);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700283
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700284 return result;
285}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700286
Chia-I Wufccbfe42016-04-28 14:01:30 +0800287VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700288 dispatch_key key = get_dispatch_key(instance);
289 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600290 SwpInstance *pInstance = NULL;
291 {
292 auto it = my_data->instanceMap.find(instance);
293 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
294 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700295
Ian Elliott32311832016-02-04 08:17:18 -0700296 // Call down the call chain:
297 my_data->instance_dispatch_table->DestroyInstance(instance, pAllocator);
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700298
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600299 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott32311832016-02-04 08:17:18 -0700300
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600301 // Enable the temporary callback(s) here to catch cleanup issues:
302 bool callback_setup = false;
303 if (my_data->num_tmp_callbacks > 0) {
304 if (!layer_enable_tmp_callbacks(my_data->report_data, my_data->num_tmp_callbacks, my_data->tmp_dbg_create_infos,
305 my_data->tmp_callbacks)) {
306 callback_setup = true;
307 }
308 }
309
Ian Elliott32311832016-02-04 08:17:18 -0700310 // Do additional internal cleanup:
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700311 if (pInstance) {
312 // Delete all of the SwpPhysicalDevice's, SwpSurface's, and the
313 // SwpInstance associated with this instance:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700314 for (auto it = pInstance->physicalDevices.begin(); it != pInstance->physicalDevices.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 SwpPhysicalDevice *pPhysicalDevice = it->second;
318 if (pPhysicalDevice) {
Ian Elliott458696a2016-02-04 06:11:17 -0700319 if (pPhysicalDevice->pDevice) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700320 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Ian Elliott458696a2016-02-04 06:11:17 -0700321 "%s() called before all of its associated "
322 "VkDevices were destroyed.",
323 __FUNCTION__);
324 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700325 free(pPhysicalDevice->pSurfaceFormats);
326 free(pPhysicalDevice->pPresentModes);
327 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700328
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700329 // Erase the SwpPhysicalDevice's from the my_data->physicalDeviceMap (which
330 // are simply pointed to by the SwpInstance):
331 my_data->physicalDeviceMap.erase(it->second->physicalDevice);
332 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700333 for (auto it = pInstance->surfaces.begin(); it != pInstance->surfaces.end(); it++) {
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700334
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700335 // Free memory that was allocated for/by this SwpPhysicalDevice:
336 SwpSurface *pSurface = it->second;
337 if (pSurface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700338 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700339 "%s() called before all of its associated "
340 "VkSurfaceKHRs were destroyed.",
341 __FUNCTION__);
342 }
343 }
344 my_data->instanceMap.erase(instance);
345 }
Mark Lobodzinski3c99d552016-02-04 13:50:23 -0700346
Ian Elliotted6b5ac2016-04-28 09:08:13 -0600347 // Disable and cleanup the temporary callback(s):
348 if (callback_setup) {
349 layer_disable_tmp_callbacks(my_data->report_data, my_data->num_tmp_callbacks, my_data->tmp_callbacks);
350 }
351 if (my_data->num_tmp_callbacks > 0) {
352 layer_free_tmp_callbacks(my_data->tmp_dbg_create_infos, my_data->tmp_callbacks);
353 my_data->num_tmp_callbacks = 0;
354 }
355
Mark Lobodzinski3c99d552016-02-04 13:50:23 -0700356 // Clean up logging callback, if any
357 while (my_data->logging_callback.size() > 0) {
358 VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
359 layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
360 my_data->logging_callback.pop_back();
361 }
362 layer_debug_report_destroy_instance(my_data->report_data);
363
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700364 delete my_data->instance_dispatch_table;
365 layer_data_map.erase(key);
366}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700367
Chia-I Wufccbfe42016-04-28 14:01:30 +0800368VKAPI_ATTR void VKAPI_CALL
369GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount,
370 VkQueueFamilyProperties *pQueueFamilyProperties) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700371 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -0700372
373 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700374 my_data->instance_dispatch_table->GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount,
375 pQueueFamilyProperties);
Ian Elliott32311832016-02-04 08:17:18 -0700376
377 // Record the result of this query:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600378 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600379 SwpPhysicalDevice *pPhysicalDevice = NULL;
380 {
381 auto it = my_data->physicalDeviceMap.find(physicalDevice);
382 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
383 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700384 if (pPhysicalDevice && pQueueFamilyPropertyCount && !pQueueFamilyProperties) {
Ian Elliott32311832016-02-04 08:17:18 -0700385 pPhysicalDevice->gotQueueFamilyPropertyCount = true;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700386 pPhysicalDevice->numOfQueueFamilies = *pQueueFamilyPropertyCount;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700387 }
388}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700389
390#ifdef VK_USE_PLATFORM_ANDROID_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800391VKAPI_ATTR VkResult VKAPI_CALL
392CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo,
393 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700394 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600395 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700396 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600397 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600398 SwpInstance *pInstance = NULL;
399 {
400 auto it = my_data->instanceMap.find(instance);
401 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
402 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700403
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700404 // Validate that the platform extension was enabled:
Cody Northropd08141b2016-02-01 09:52:07 -0700405 if (pInstance && !pInstance->androidSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700406 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
407 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
408 VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700409 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700410
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700411 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700412 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700413 } else {
414 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700415 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700416 "VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR");
417 }
418 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700419 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700420 }
421 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600422 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700423
Dustin Graves080069b2016-04-05 13:48:15 -0600424 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700425 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700426 result = my_data->instance_dispatch_table->CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600427 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700428
Ian Elliott32311832016-02-04 08:17:18 -0700429 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600430 {
431 auto it = my_data->instanceMap.find(instance);
432 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
433 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700434 if ((result == VK_SUCCESS) && pInstance && pSurface) {
435 // Record the VkSurfaceKHR returned by the ICD:
436 my_data->surfaceMap[*pSurface].surface = *pSurface;
437 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700438 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700439 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
440 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
441 // Point to the associated SwpInstance:
442 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
443 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600444 lock.unlock();
445
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700446 return result;
447 }
448 return VK_ERROR_VALIDATION_FAILED_EXT;
449}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700450#endif // VK_USE_PLATFORM_ANDROID_KHR
451
452#ifdef VK_USE_PLATFORM_MIR_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800453VKAPI_ATTR VkResult VKAPI_CALL
454CreateMirSurfaceKHR(VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
455 VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700456 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600457 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700458 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600459 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600460 SwpInstance *pInstance = NULL;
461 {
462 auto it = my_data->instanceMap.find(instance);
463 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
464 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700465
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700466 // Validate that the platform extension was enabled:
467 if (pInstance && !pInstance->mirSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700468 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
469 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
470 VK_KHR_MIR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700471 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700472
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700473 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700474 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700475 } else {
476 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700477 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700478 "VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR");
479 }
480 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700481 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700482 }
483 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600484 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700485
Dustin Graves080069b2016-04-05 13:48:15 -0600486 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700487 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700488 result = my_data->instance_dispatch_table->CreateMirSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600489 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700490
Ian Elliott32311832016-02-04 08:17:18 -0700491 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600492 {
493 auto it = my_data->instanceMap.find(instance);
494 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
495 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700496 if ((result == VK_SUCCESS) && pInstance && pSurface) {
497 // Record the VkSurfaceKHR returned by the ICD:
498 my_data->surfaceMap[*pSurface].surface = *pSurface;
499 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700500 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700501 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
502 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
503 // Point to the associated SwpInstance:
504 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
505 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600506 lock.unlock();
507
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700508 return result;
509 }
510 return VK_ERROR_VALIDATION_FAILED_EXT;
511}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700512
Chia-I Wufccbfe42016-04-28 14:01:30 +0800513VKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceMirPresentationSupportKHR(VkPhysicalDevice physicalDevice,
514 uint32_t queueFamilyIndex,
515 MirConnection *connection) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700516 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600517 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700518 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600519 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600520 SwpPhysicalDevice *pPhysicalDevice = NULL;
521 {
522 auto it = my_data->physicalDeviceMap.find(physicalDevice);
523 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
524 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700525
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700526 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700527 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->mirSurfaceExtensionEnabled) {
528 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700529 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700530 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
531 VK_KHR_MIR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700532 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700533 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
534 skipCall |=
535 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
536 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700537 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600538 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700539
Dustin Graves080069b2016-04-05 13:48:15 -0600540 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700541 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700542 result = my_data->instance_dispatch_table->GetPhysicalDeviceMirPresentationSupportKHR(physicalDevice, queueFamilyIndex,
543 connection);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700544 }
545 return result;
546}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700547#endif // VK_USE_PLATFORM_MIR_KHR
548
549#ifdef VK_USE_PLATFORM_WAYLAND_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800550VKAPI_ATTR VkResult VKAPI_CALL
551CreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
552 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700553 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600554 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700555 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600556 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600557 SwpInstance *pInstance = NULL;
558 {
559 auto it = my_data->instanceMap.find(instance);
560 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
561 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700562
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700563 // Validate that the platform extension was enabled:
564 if (pInstance && !pInstance->waylandSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700565 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
566 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
567 VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700568 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700569
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700570 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700571 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700572 } else {
573 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700574 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700575 "VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR");
576 }
577 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700578 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700579 }
580 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600581 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700582
Dustin Graves080069b2016-04-05 13:48:15 -0600583 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700584 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700585 result = my_data->instance_dispatch_table->CreateWaylandSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600586 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700587
Ian Elliott32311832016-02-04 08:17:18 -0700588 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600589 {
590 auto it = my_data->instanceMap.find(instance);
591 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
592 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700593 if ((result == VK_SUCCESS) && pInstance && pSurface) {
594 // Record the VkSurfaceKHR returned by the ICD:
595 my_data->surfaceMap[*pSurface].surface = *pSurface;
596 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700597 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700598 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
599 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
600 // Point to the associated SwpInstance:
601 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
602 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600603 lock.unlock();
604
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700605 return result;
606 }
607 return VK_ERROR_VALIDATION_FAILED_EXT;
608}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700609
Chia-I Wufccbfe42016-04-28 14:01:30 +0800610VKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,
611 uint32_t queueFamilyIndex,
612 struct wl_display *display) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700613 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600614 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700615 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600616 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600617 SwpPhysicalDevice *pPhysicalDevice = NULL;
618 {
619 auto it = my_data->physicalDeviceMap.find(physicalDevice);
620 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
621 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700622
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700623 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700624 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->waylandSurfaceExtensionEnabled) {
625 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700626 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700627 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
628 VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700629 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700630 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
631 skipCall |=
632 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
633 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700634 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600635 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700636
Dustin Graves080069b2016-04-05 13:48:15 -0600637 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700638 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700639 result = my_data->instance_dispatch_table->GetPhysicalDeviceWaylandPresentationSupportKHR(physicalDevice, queueFamilyIndex,
640 display);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700641 }
642 return result;
643}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700644#endif // VK_USE_PLATFORM_WAYLAND_KHR
645
646#ifdef VK_USE_PLATFORM_WIN32_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800647VKAPI_ATTR VkResult VKAPI_CALL
648CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
649 const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700650 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600651 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700652 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600653 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600654 SwpInstance *pInstance = NULL;
655 {
656 auto it = my_data->instanceMap.find(instance);
657 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
658 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700659
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700660 // Validate that the platform extension was enabled:
661 if (pInstance && !pInstance->win32SurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700662 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
663 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
664 VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700665 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700666
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700667 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700668 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700669 } else {
670 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700671 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700672 "VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR");
673 }
674 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700675 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700676 }
677 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600678 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700679
Dustin Graves080069b2016-04-05 13:48:15 -0600680 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700681 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700682 result = my_data->instance_dispatch_table->CreateWin32SurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600683 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700684
Ian Elliott32311832016-02-04 08:17:18 -0700685 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600686 {
687 auto it = my_data->instanceMap.find(instance);
688 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
689 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700690 if ((result == VK_SUCCESS) && pInstance && pSurface) {
691 // Record the VkSurfaceKHR returned by the ICD:
692 my_data->surfaceMap[*pSurface].surface = *pSurface;
693 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700694 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700695 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
696 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
697 // Point to the associated SwpInstance:
698 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
699 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600700 lock.unlock();
701
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700702 return result;
703 }
704 return VK_ERROR_VALIDATION_FAILED_EXT;
705}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700706
Chia-I Wufccbfe42016-04-28 14:01:30 +0800707VKAPI_ATTR VkBool32 VKAPI_CALL
708GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700709 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600710 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700711 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600712 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600713 SwpPhysicalDevice *pPhysicalDevice = NULL;
714 {
715 auto it = my_data->physicalDeviceMap.find(physicalDevice);
716 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
717 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700718
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700719 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700720 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->win32SurfaceExtensionEnabled) {
721 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700722 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700723 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
724 VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700725 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700726 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
727 skipCall |=
728 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
729 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700730 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600731 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700732
Dustin Graves080069b2016-04-05 13:48:15 -0600733 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700734 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700735 result = my_data->instance_dispatch_table->GetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700736 }
737 return result;
738}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700739#endif // VK_USE_PLATFORM_WIN32_KHR
740
741#ifdef VK_USE_PLATFORM_XCB_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800742VKAPI_ATTR VkResult VKAPI_CALL
743CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700744 VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700745 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600746 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700747 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600748 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600749 SwpInstance *pInstance = NULL;
750 {
751 auto it = my_data->instanceMap.find(instance);
752 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
753 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700754
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700755 // Validate that the platform extension was enabled:
756 if (pInstance && !pInstance->xcbSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700757 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
758 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
759 VK_KHR_XCB_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700760 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700761
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700762 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700763 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700764 } else {
765 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700766 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700767 "VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR");
768 }
769 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700770 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700771 }
772 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600773 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700774
Dustin Graves080069b2016-04-05 13:48:15 -0600775 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700776 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700777 result = my_data->instance_dispatch_table->CreateXcbSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600778 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700779
Ian Elliott32311832016-02-04 08:17:18 -0700780 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600781 {
782 auto it = my_data->instanceMap.find(instance);
783 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
784 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700785 if ((result == VK_SUCCESS) && pInstance && pSurface) {
786 // Record the VkSurfaceKHR returned by the ICD:
787 my_data->surfaceMap[*pSurface].surface = *pSurface;
788 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700789 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700790 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
791 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
792 // Point to the associated SwpInstance:
793 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
794 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600795 lock.unlock();
796
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700797 return result;
798 }
799 return VK_ERROR_VALIDATION_FAILED_EXT;
800}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700801
Chia-I Wufccbfe42016-04-28 14:01:30 +0800802VKAPI_ATTR VkBool32 VKAPI_CALL
803GetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex,
804 xcb_connection_t *connection, xcb_visualid_t visual_id) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700805 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600806 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700807 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600808 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600809 SwpPhysicalDevice *pPhysicalDevice = NULL;
810 {
811 auto it = my_data->physicalDeviceMap.find(physicalDevice);
812 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
813 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700814
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700815 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700816 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->xcbSurfaceExtensionEnabled) {
817 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700818 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700819 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
820 VK_KHR_XCB_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700821 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700822 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
823 skipCall |=
824 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
825 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700826 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600827 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700828
Dustin Graves080069b2016-04-05 13:48:15 -0600829 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700830 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700831 result = my_data->instance_dispatch_table->GetPhysicalDeviceXcbPresentationSupportKHR(physicalDevice, queueFamilyIndex,
832 connection, visual_id);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700833 }
834 return result;
835}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700836#endif // VK_USE_PLATFORM_XCB_KHR
837
838#ifdef VK_USE_PLATFORM_XLIB_KHR
Chia-I Wufccbfe42016-04-28 14:01:30 +0800839VKAPI_ATTR VkResult VKAPI_CALL
840CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
841 VkSurfaceKHR *pSurface) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700842 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -0600843 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700844 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600845 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600846 SwpInstance *pInstance = NULL;
847 {
848 auto it = my_data->instanceMap.find(instance);
849 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
850 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700851
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700852 // Validate that the platform extension was enabled:
853 if (pInstance && !pInstance->xlibSurfaceExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700854 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
855 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
856 VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700857 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700858
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700859 if (!pCreateInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700860 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700861 } else {
862 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700863 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700864 "VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR");
865 }
866 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700867 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700868 }
869 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600870 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700871
Dustin Graves080069b2016-04-05 13:48:15 -0600872 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700873 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700874 result = my_data->instance_dispatch_table->CreateXlibSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600875 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700876
Ian Elliott32311832016-02-04 08:17:18 -0700877 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -0600878 {
879 auto it = my_data->instanceMap.find(instance);
880 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
881 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700882 if ((result == VK_SUCCESS) && pInstance && pSurface) {
883 // Record the VkSurfaceKHR returned by the ICD:
884 my_data->surfaceMap[*pSurface].surface = *pSurface;
885 my_data->surfaceMap[*pSurface].pInstance = pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700886 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700887 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
888 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
889 // Point to the associated SwpInstance:
890 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
891 }
Ian Elliott970a2bd2016-06-21 11:08:43 -0600892 lock.unlock();
893
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700894 return result;
895 }
896 return VK_ERROR_VALIDATION_FAILED_EXT;
897}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700898
Chia-I Wufccbfe42016-04-28 14:01:30 +0800899VKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
900 uint32_t queueFamilyIndex,
901 Display *dpy, VisualID visualID) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700902 VkBool32 result = VK_FALSE;
Dustin Graves080069b2016-04-05 13:48:15 -0600903 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700904 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600905 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -0600906 SwpPhysicalDevice *pPhysicalDevice = NULL;
907 {
908 auto it = my_data->physicalDeviceMap.find(physicalDevice);
909 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
910 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700911
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700912 // Validate that the platform extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700913 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->xlibSurfaceExtensionEnabled) {
914 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700915 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700916 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
917 VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700918 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700919 if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
920 skipCall |=
921 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
922 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700923 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -0600924 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700925
Dustin Graves080069b2016-04-05 13:48:15 -0600926 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700927 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700928 result = my_data->instance_dispatch_table->GetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex,
929 dpy, visualID);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700930 }
931 return result;
932}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -0700933#endif // VK_USE_PLATFORM_XLIB_KHR
934
Petros Bantolas2b40be72016-04-15 11:02:59 +0100935VKAPI_ATTR VkResult VKAPI_CALL
936GetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkDisplayPropertiesKHR *pProperties) {
937 VkResult result = VK_SUCCESS;
938 bool skipCall = false;
939 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
940 std::unique_lock<std::mutex> lock(global_lock);
941 SwpPhysicalDevice *pPhysicalDevice = NULL;
942 {
943 auto it = my_data->physicalDeviceMap.find(physicalDevice);
944 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
945 }
946
947 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
948 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
949 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
950 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
951 VK_KHR_DISPLAY_EXTENSION_NAME);
952 }
953
954 if (!pPropertyCount) {
955 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pPropertyCount");
956 }
957 lock.unlock();
958
959 if (!skipCall) {
960 result = my_data->instance_dispatch_table->GetPhysicalDeviceDisplayPropertiesKHR(physicalDevice, pPropertyCount, pProperties);
961 return result;
962 }
963 return VK_ERROR_VALIDATION_FAILED_EXT;
964}
965
Petros Bantolas2b40be72016-04-15 11:02:59 +0100966VKAPI_ATTR VkResult VKAPI_CALL
967GetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkDisplayPlanePropertiesKHR *pProperties) {
968 VkResult result = VK_SUCCESS;
969 bool skipCall = false;
970 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
971 std::unique_lock<std::mutex> lock(global_lock);
972 SwpPhysicalDevice *pPhysicalDevice = NULL;
973 {
974 auto it = my_data->physicalDeviceMap.find(physicalDevice);
975 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
976 }
977
978 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
979 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
980 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
981 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
982 VK_KHR_DISPLAY_EXTENSION_NAME);
983 }
984
985 if (!pPropertyCount) {
986 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pPropertyCount");
987 }
988 lock.unlock();
989
990 if (!skipCall) {
991 result = my_data->instance_dispatch_table->GetPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, pPropertyCount, pProperties);
992
993 lock.lock();
994 if (!pPhysicalDevice->gotDisplayPlanePropertyCount)
995 {
996 pPhysicalDevice->displayPlanePropertyCount = *pPropertyCount;
997 pPhysicalDevice->gotDisplayPlanePropertyCount = true;
998 }
999 lock.unlock();
1000
1001 return result;
1002 }
1003 return VK_ERROR_VALIDATION_FAILED_EXT;
1004}
1005
1006VKAPI_ATTR VkResult VKAPI_CALL
1007GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays) {
1008 VkResult result = VK_SUCCESS;
1009 bool skipCall = false;
1010 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1011 std::unique_lock<std::mutex> lock(global_lock);
1012 SwpPhysicalDevice *pPhysicalDevice = NULL;
1013 {
1014 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1015 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1016 }
1017
1018 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
1019 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1020 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1021 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1022 VK_KHR_DISPLAY_EXTENSION_NAME);
1023 }
1024
1025 if (!pDisplayCount) {
1026 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pDisplayCount");
1027 }
1028
Jon Ashburn5e026df2016-06-15 08:19:07 -06001029 if (!pPhysicalDevice->gotDisplayPlanePropertyCount)
Petros Bantolas2b40be72016-04-15 11:02:59 +01001030 {
1031 LOG_WARNING(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
1032 SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY,
1033 "Potential problem with calling %s() without first querying vkGetPhysicalDeviceDisplayPlanePropertiesKHR.",
1034 __FUNCTION__);
1035 }
1036
Jon Ashburn5e026df2016-06-15 08:19:07 -06001037 if (pPhysicalDevice->gotDisplayPlanePropertyCount && planeIndex >= pPhysicalDevice->gotDisplayPlanePropertyCount)
Petros Bantolas2b40be72016-04-15 11:02:59 +01001038 {
1039 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
1040 SWAPCHAIN_PLANE_INDEX_TOO_LARGE,
1041 "%s(): %s must be in the range [0, %d] that was returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR. Do you have the plane index hardcoded?",
1042 __FUNCTION__,
1043 "planeIndex",
Jon Ashburn5e026df2016-06-15 08:19:07 -06001044 pPhysicalDevice->displayPlanePropertyCount - 1);
Petros Bantolas2b40be72016-04-15 11:02:59 +01001045 }
1046 lock.unlock();
1047
1048 if (!skipCall) {
1049 result = my_data->instance_dispatch_table->GetDisplayPlaneSupportedDisplaysKHR(physicalDevice, planeIndex, pDisplayCount, pDisplays);
1050
1051 return result;
1052 }
1053 return VK_ERROR_VALIDATION_FAILED_EXT;
1054}
1055
1056VKAPI_ATTR VkResult VKAPI_CALL
1057GetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties) {
1058 VkResult result = VK_SUCCESS;
1059 bool skipCall = false;
1060 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1061 std::unique_lock<std::mutex> lock(global_lock);
1062 SwpPhysicalDevice *pPhysicalDevice = NULL;
1063 {
1064 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1065 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1066 }
1067
1068 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
1069 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1070 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1071 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1072 VK_KHR_DISPLAY_EXTENSION_NAME);
1073 }
1074
1075 if (!pPropertyCount) {
1076 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pPropertyCount");
1077 }
1078 lock.unlock();
1079
1080 if (!skipCall) {
1081 result = my_data->instance_dispatch_table->GetDisplayModePropertiesKHR(physicalDevice, display, pPropertyCount, pProperties);
1082 return result;
1083 }
1084 return VK_ERROR_VALIDATION_FAILED_EXT;
1085}
1086
1087VKAPI_ATTR VkResult VKAPI_CALL
1088CreateDisplayModeKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode) {
1089 VkResult result = VK_SUCCESS;
1090 bool skipCall = false;
1091 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1092 std::unique_lock<std::mutex> lock(global_lock);
1093 SwpPhysicalDevice *pPhysicalDevice = NULL;
1094 {
1095 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1096 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1097 }
1098
1099 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
1100 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1101 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1102 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1103 VK_KHR_DISPLAY_EXTENSION_NAME);
1104 }
1105
1106 if (!pCreateInfo) {
1107 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pCreateInfo");
1108 }
1109 lock.unlock();
1110
1111 if (!skipCall) {
1112 result = my_data->instance_dispatch_table->CreateDisplayModeKHR(physicalDevice, display, pCreateInfo, pAllocator, pMode);
1113 return result;
1114 }
1115
1116 return VK_ERROR_VALIDATION_FAILED_EXT;
1117}
1118
1119VKAPI_ATTR VkResult VKAPI_CALL
1120GetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR* pCapabilities) {
1121 VkResult result = VK_SUCCESS;
1122 bool skipCall = false;
1123 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1124 std::unique_lock<std::mutex> lock(global_lock);
1125 SwpPhysicalDevice *pPhysicalDevice = NULL;
1126 {
1127 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1128 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1129 }
1130
1131 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
1132 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1133 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1134 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1135 VK_KHR_DISPLAY_EXTENSION_NAME);
1136 }
1137
Jon Ashburn5e026df2016-06-15 08:19:07 -06001138 if (!pPhysicalDevice->gotDisplayPlanePropertyCount)
Petros Bantolas2b40be72016-04-15 11:02:59 +01001139 {
1140 LOG_WARNING(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
1141 SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY,
1142 "Potential problem with calling %s() without first querying vkGetPhysicalDeviceDisplayPlanePropertiesKHR.",
1143 __FUNCTION__);
1144 }
1145
Jon Ashburn5e026df2016-06-15 08:19:07 -06001146 if (pPhysicalDevice->gotDisplayPlanePropertyCount && planeIndex >= pPhysicalDevice->displayPlanePropertyCount)
Petros Bantolas2b40be72016-04-15 11:02:59 +01001147 {
1148 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
1149 SWAPCHAIN_PLANE_INDEX_TOO_LARGE,
1150 "%s(): %s must be in the range [0, %d] that was returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR. Do you have the plane index hardcoded?",
1151 __FUNCTION__,
1152 "planeIndex",
Jon Ashburn5e026df2016-06-15 08:19:07 -06001153 pPhysicalDevice->displayPlanePropertyCount - 1);
Petros Bantolas2b40be72016-04-15 11:02:59 +01001154 }
1155
1156 if (!pCapabilities) {
1157 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pCapabilities");
1158 }
1159 lock.unlock();
1160
1161 if (!skipCall) {
1162 result = my_data->instance_dispatch_table->GetDisplayPlaneCapabilitiesKHR(physicalDevice, mode, planeIndex, pCapabilities);
1163 return result;
1164 }
1165
1166 return VK_ERROR_VALIDATION_FAILED_EXT;
1167}
1168
1169VKAPI_ATTR VkResult VKAPI_CALL
1170CreateDisplayPlaneSurfaceKHR(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
1171 VkSurfaceKHR *pSurface) {
1172 VkResult result = VK_SUCCESS;
1173 bool skipCall = false;
1174 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1175 std::unique_lock<std::mutex> lock(global_lock);
1176 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
1177
1178 // Validate that the platform extension was enabled:
1179 if (pInstance && !pInstance->displayExtensionEnabled) {
1180 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1181 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1182 VK_KHR_DISPLAY_EXTENSION_NAME);
1183 }
1184
1185 if (!pCreateInfo) {
1186 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
1187 } else {
1188 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR) {
1189 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
1190 "VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR");
1191 }
1192 if (pCreateInfo->pNext != NULL) {
1193 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
1194 }
1195 }
1196
1197 if (!skipCall) {
1198 // Call down the call chain:
1199 lock.unlock();
1200 result = my_data->instance_dispatch_table->CreateDisplayPlaneSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
1201 lock.lock();
1202
1203 // Obtain this pointer again after locking:
1204 pInstance = &(my_data->instanceMap[instance]);
1205 if ((result == VK_SUCCESS) && pInstance && pSurface) {
1206 // Record the VkSurfaceKHR returned by the ICD:
1207 my_data->surfaceMap[*pSurface].surface = *pSurface;
1208 my_data->surfaceMap[*pSurface].pInstance = pInstance;
1209 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
1210 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
1211 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
1212 // Point to the associated SwpInstance:
1213 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
1214 }
1215 lock.unlock();
1216 return result;
1217 }
1218 return VK_ERROR_VALIDATION_FAILED_EXT;
1219}
1220
Chia-I Wufccbfe42016-04-28 14:01:30 +08001221VKAPI_ATTR void VKAPI_CALL
1222DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) {
Dustin Graves080069b2016-04-05 13:48:15 -06001223 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001224 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001225 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001226 SwpSurface *pSurface = NULL;
1227 {
1228 auto it = my_data->surfaceMap.find(surface);
1229 pSurface = (it == my_data->surfaceMap.end()) ? NULL : &it->second;
1230 }
1231 SwpInstance *pInstance = NULL;
1232 {
1233 auto it = my_data->instanceMap.find(instance);
1234 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
1235 }
Ian Elliottf6b8c782016-04-29 13:03:17 -06001236
1237 // Validate that the platform extension was enabled:
1238 if (pInstance && !pInstance->surfaceExtensionEnabled) {
1239 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1240 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1241 VK_KHR_SURFACE_EXTENSION_NAME);
1242 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001243
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001244 // Regardless of skipCall value, do some internal cleanup:
1245 if (pSurface) {
1246 // Delete the SwpSurface associated with this surface:
1247 if (pSurface->pInstance) {
1248 pSurface->pInstance->surfaces.erase(surface);
1249 }
1250 if (!pSurface->swapchains.empty()) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001251 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001252 "%s() called before all of its associated "
1253 "VkSwapchainKHRs were destroyed.",
1254 __FUNCTION__);
1255 // Empty and then delete all SwpSwapchain's
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001256 for (auto it = pSurface->swapchains.begin(); it != pSurface->swapchains.end(); it++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001257 // Delete all SwpImage's
1258 it->second->images.clear();
1259 // In case the swapchain's device hasn't been destroyed yet
1260 // (which isn't likely, but is possible), delete its
1261 // association with this swapchain (i.e. so we can't point to
1262 // this swpchain from that device, later on):
1263 if (it->second->pDevice) {
1264 it->second->pDevice->swapchains.clear();
1265 }
1266 }
1267 pSurface->swapchains.clear();
1268 }
1269 if ((pAllocator != NULL) != pSurface->usedAllocatorToCreate) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001270 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001271 "%s() called with incompatible pAllocator from when "
1272 "the object was created.",
1273 __FUNCTION__);
1274 }
1275 my_data->surfaceMap.erase(surface);
1276 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001277 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001278
Dustin Graves080069b2016-04-05 13:48:15 -06001279 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001280 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001281 my_data->instance_dispatch_table->DestroySurfaceKHR(instance, surface, pAllocator);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001282 }
1283}
1284
Chia-I Wufccbfe42016-04-28 14:01:30 +08001285VKAPI_ATTR VkResult VKAPI_CALL
1286EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001287 VkResult result = VK_SUCCESS;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001288 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001289
1290 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001291 result = my_data->instance_dispatch_table->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
Ian Elliott32311832016-02-04 08:17:18 -07001292
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001293 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001294 SwpInstance *pInstance = NULL;
1295 {
1296 auto it = my_data->instanceMap.find(instance);
1297 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
1298 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001299 if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices && (*pPhysicalDeviceCount > 0)) {
Ian Elliott32311832016-02-04 08:17:18 -07001300 // Record the VkPhysicalDevices returned by the ICD:
1301 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001302 my_data->physicalDeviceMap[pPhysicalDevices[i]].physicalDevice = pPhysicalDevices[i];
Ian Elliott32311832016-02-04 08:17:18 -07001303 my_data->physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance;
1304 my_data->physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL;
1305 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotQueueFamilyPropertyCount = false;
1306 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotSurfaceCapabilities = false;
1307 my_data->physicalDeviceMap[pPhysicalDevices[i]].surfaceFormatCount = 0;
1308 my_data->physicalDeviceMap[pPhysicalDevices[i]].pSurfaceFormats = NULL;
1309 my_data->physicalDeviceMap[pPhysicalDevices[i]].presentModeCount = 0;
1310 my_data->physicalDeviceMap[pPhysicalDevices[i]].pPresentModes = NULL;
1311 // Point to the associated SwpInstance:
1312 if (pInstance) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001313 pInstance->physicalDevices[pPhysicalDevices[i]] = &my_data->physicalDeviceMap[pPhysicalDevices[i]];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001314 }
1315 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001316 }
Ian Elliotta3c69bc2016-02-04 15:34:59 -07001317 return result;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001318}
1319
Chia-I Wufccbfe42016-04-28 14:01:30 +08001320VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice physicalDevice,
1321 const VkDeviceCreateInfo *pCreateInfo,
1322 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Chia-I Wua6737532016-04-28 16:04:15 +08001323 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001324 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
1325
1326 assert(chain_info->u.pLayerInfo);
1327 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
1328 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Chia-I Wua6737532016-04-28 16:04:15 +08001329 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001330 if (fpCreateDevice == NULL) {
1331 return VK_ERROR_INITIALIZATION_FAILED;
1332 }
1333
1334 // Advance the link info for the next element on the chain
1335 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
1336
1337 VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1338 if (result != VK_SUCCESS) {
1339 return result;
1340 }
1341
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001342 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001343 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
1344
1345 // Setup device dispatch table
1346 my_device_data->device_dispatch_table = new VkLayerDispatchTable;
1347 layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
1348
1349 my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
1350 createDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice);
1351
1352 return result;
1353}
1354
Chia-I Wufccbfe42016-04-28 14:01:30 +08001355VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001356 dispatch_key key = get_dispatch_key(device);
1357 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001358
1359 // Call down the call chain:
1360 my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
1361
1362 // Do some internal cleanup:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001363 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001364 SwpDevice *pDevice = NULL;
1365 {
1366 auto it = my_data->deviceMap.find(device);
1367 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1368 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001369 if (pDevice) {
1370 // Delete the SwpDevice associated with this device:
1371 if (pDevice->pPhysicalDevice) {
1372 pDevice->pPhysicalDevice->pDevice = NULL;
1373 }
1374 if (!pDevice->swapchains.empty()) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001375 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001376 "%s() called before all of its associated "
1377 "VkSwapchainKHRs were destroyed.",
1378 __FUNCTION__);
1379 // Empty and then delete all SwpSwapchain's
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001380 for (auto it = pDevice->swapchains.begin(); it != pDevice->swapchains.end(); it++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001381 // Delete all SwpImage's
1382 it->second->images.clear();
1383 // In case the swapchain's surface hasn't been destroyed yet
1384 // (which is likely) delete its association with this swapchain
1385 // (i.e. so we can't point to this swpchain from that surface,
1386 // later on):
1387 if (it->second->pSurface) {
1388 it->second->pSurface->swapchains.clear();
1389 }
1390 }
1391 pDevice->swapchains.clear();
1392 }
1393 my_data->deviceMap.erase(device);
1394 }
1395 delete my_data->device_dispatch_table;
1396 layer_data_map.erase(key);
1397}
1398
Chia-I Wufccbfe42016-04-28 14:01:30 +08001399VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
1400 uint32_t queueFamilyIndex, VkSurfaceKHR surface,
1401 VkBool32 *pSupported) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001402 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001403 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001404 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001405 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001406 SwpPhysicalDevice *pPhysicalDevice = NULL;
1407 {
1408 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1409 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1410 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001411
1412 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001413 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1414 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001415 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001416 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1417 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001418 }
1419 if (!pPhysicalDevice->gotQueueFamilyPropertyCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001420 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, "VkPhysicalDevice",
1421 SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES, "%s() called before calling the "
1422 "vkGetPhysicalDeviceQueueFamilyProperties "
1423 "function.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001424 __FUNCTION__);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001425 } else if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
1426 skipCall |=
1427 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
1428 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001429 }
1430 if (!pSupported) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001431 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSupported");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001432 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001433 lock.unlock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001434
Dustin Graves080069b2016-04-05 13:48:15 -06001435 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001436 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001437 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface,
1438 pSupported);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001439 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001440
Ian Elliott32311832016-02-04 08:17:18 -07001441 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001442 {
1443 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1444 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1445 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001446 if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
1447 // Record the result of this query:
1448 SwpInstance *pInstance = pPhysicalDevice->pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001449 SwpSurface *pSurface = (pInstance) ? pInstance->surfaces[surface] : NULL;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001450 if (pSurface) {
1451 pPhysicalDevice->supportedSurfaces[surface] = pSurface;
1452 if (!pSurface->numQueueFamilyIndexSupport) {
1453 if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001454 pSurface->pQueueFamilyIndexSupport =
1455 (VkBool32 *)malloc(pPhysicalDevice->numOfQueueFamilies * sizeof(VkBool32));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001456 if (pSurface->pQueueFamilyIndexSupport != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001457 pSurface->numQueueFamilyIndexSupport = pPhysicalDevice->numOfQueueFamilies;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001458 }
1459 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001460 }
1461 if (pSurface->numQueueFamilyIndexSupport) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001462 pSurface->pQueueFamilyIndexSupport[queueFamilyIndex] = *pSupported;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001463 }
1464 }
1465 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001466 lock.unlock();
1467
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001468 return result;
1469 }
1470 return VK_ERROR_VALIDATION_FAILED_EXT;
1471}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001472
Chia-I Wufccbfe42016-04-28 14:01:30 +08001473VKAPI_ATTR VkResult VKAPI_CALL
1474GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
1475 VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001476 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001477 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001478 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001479 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001480 SwpPhysicalDevice *pPhysicalDevice = NULL;
1481 {
1482 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1483 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1484 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001485
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001486 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001487 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1488 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001489 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001490 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1491 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001492 }
1493 if (!pSurfaceCapabilities) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001494 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceCapabilities");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001495 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001496 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001497
Dustin Graves080069b2016-04-05 13:48:15 -06001498 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001499 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001500 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface,
1501 pSurfaceCapabilities);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001502 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001503
Ian Elliott32311832016-02-04 08:17:18 -07001504 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001505 {
1506 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1507 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1508 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001509 if ((result == VK_SUCCESS) && pPhysicalDevice) {
1510 // Record the result of this query:
1511 pPhysicalDevice->gotSurfaceCapabilities = true;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001512 // FIXME: NEED TO COPY THIS DATA, BECAUSE pSurfaceCapabilities POINTS TO APP-ALLOCATED DATA
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001513 pPhysicalDevice->surfaceCapabilities = *pSurfaceCapabilities;
1514 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001515 lock.unlock();
1516
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001517 return result;
1518 }
1519 return VK_ERROR_VALIDATION_FAILED_EXT;
1520}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001521
Chia-I Wufccbfe42016-04-28 14:01:30 +08001522VKAPI_ATTR VkResult VKAPI_CALL
1523GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount,
1524 VkSurfaceFormatKHR *pSurfaceFormats) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001525 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001526 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001527 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001528 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001529 SwpPhysicalDevice *pPhysicalDevice = NULL;
1530 {
1531 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1532 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1533 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001534
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001535 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001536 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1537 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001538 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001539 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1540 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001541 }
1542 if (!pSurfaceFormatCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001543 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceFormatCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001544 } else if (pPhysicalDevice && pSurfaceFormats) {
1545 // Compare the preliminary value of *pSurfaceFormatCount with the
1546 // value this time:
1547 if (pPhysicalDevice->surfaceFormatCount == 0) {
1548 // Since we haven't recorded a preliminary value of
1549 // *pSurfaceFormatCount, that likely means that the application
1550 // didn't previously call this function with a NULL value of
1551 // pSurfaceFormats:
1552 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
1553 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1554 physicalDevice, "pSurfaceFormatCount", "pSurfaceFormats");
1555 } else if (*pSurfaceFormatCount > pPhysicalDevice->surfaceFormatCount) {
1556 skipCall |= LOG_ERROR_INVALID_COUNT(
1557 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1558 physicalDevice, "pSurfaceFormatCount", "pSurfaceFormats",
1559 *pSurfaceFormatCount, pPhysicalDevice->surfaceFormatCount);
1560 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001561 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001562 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001563
Dustin Graves080069b2016-04-05 13:48:15 -06001564 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001565 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001566 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount,
1567 pSurfaceFormats);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001568 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001569
Ian Elliott32311832016-02-04 08:17:18 -07001570 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001571 {
1572 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1573 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1574 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001575 if ((result == VK_SUCCESS) && pPhysicalDevice && !pSurfaceFormats && pSurfaceFormatCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001576 // Record the result of this preliminary query:
1577 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001578 } else if ((result == VK_SUCCESS) && pPhysicalDevice &&
1579 pSurfaceFormats && pSurfaceFormatCount &&
1580 (*pSurfaceFormatCount > 0)) {
1581 // Record the result of this query:
1582 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
1583 pPhysicalDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)malloc(*pSurfaceFormatCount * sizeof(VkSurfaceFormatKHR));
1584 if (pPhysicalDevice->pSurfaceFormats) {
1585 for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) {
1586 pPhysicalDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001587 }
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001588 } else {
1589 pPhysicalDevice->surfaceFormatCount = 0;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001590 }
1591 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001592 lock.unlock();
1593
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001594 return result;
1595 }
1596 return VK_ERROR_VALIDATION_FAILED_EXT;
1597}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001598
Chia-I Wufccbfe42016-04-28 14:01:30 +08001599VKAPI_ATTR VkResult VKAPI_CALL
1600GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pPresentModeCount,
1601 VkPresentModeKHR *pPresentModes) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001602 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001603 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001604 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001605 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001606 SwpPhysicalDevice *pPhysicalDevice = NULL;
1607 {
1608 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1609 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1610 }
Ian Elliott07adb112016-01-05 12:51:03 -07001611
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001612 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001613 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1614 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001615 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001616 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1617 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001618 }
1619 if (!pPresentModeCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001620 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pPresentModeCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001621 } else if (pPhysicalDevice && pPresentModes) {
1622 // Compare the preliminary value of *pPresentModeCount with the
1623 // value this time:
1624 if (pPhysicalDevice->presentModeCount == 0) {
1625 // Since we haven't recorded a preliminary value of
1626 // *pPresentModeCount, that likely means that the application
1627 // didn't previously call this function with a NULL value of
1628 // pPresentModes:
1629 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
1630 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1631 physicalDevice, "pPresentModeCount", "pPresentModes");
1632 } else if (*pPresentModeCount > pPhysicalDevice->presentModeCount) {
1633 skipCall |= LOG_ERROR_INVALID_COUNT(
1634 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1635 physicalDevice, "pPresentModeCount", "pPresentModes",
1636 *pPresentModeCount, pPhysicalDevice->presentModeCount);
1637 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001638 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001639 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001640
Dustin Graves080069b2016-04-05 13:48:15 -06001641 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001642 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001643 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface,
1644 pPresentModeCount, pPresentModes);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001645 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001646
Ian Elliott32311832016-02-04 08:17:18 -07001647 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001648 {
1649 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1650 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1651 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001652 if ((result == VK_SUCCESS) && pPhysicalDevice && !pPresentModes && pPresentModeCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001653 // Record the result of this preliminary query:
1654 pPhysicalDevice->presentModeCount = *pPresentModeCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001655 } else if ((result == VK_SUCCESS) && pPhysicalDevice &&
1656 pPresentModes && pPresentModeCount &&
1657 (*pPresentModeCount > 0)) {
1658 // Record the result of this query:
1659 pPhysicalDevice->presentModeCount = *pPresentModeCount;
1660 pPhysicalDevice->pPresentModes = (VkPresentModeKHR *)malloc(*pPresentModeCount * sizeof(VkPresentModeKHR));
1661 if (pPhysicalDevice->pPresentModes) {
1662 for (uint32_t i = 0; i < *pPresentModeCount; i++) {
1663 pPhysicalDevice->pPresentModes[i] = pPresentModes[i];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001664 }
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001665 } else {
1666 pPhysicalDevice->presentModeCount = 0;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001667 }
1668 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001669 lock.unlock();
1670
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001671 return result;
1672 }
1673 return VK_ERROR_VALIDATION_FAILED_EXT;
1674}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001675
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001676// This function does the up-front validation work for vkCreateSwapchainKHR(),
Dustin Graves080069b2016-04-05 13:48:15 -06001677// and returns true if a logging callback indicates that the call down the
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001678// chain should be skipped:
Dustin Graves080069b2016-04-05 13:48:15 -06001679static bool validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, VkSwapchainKHR *pSwapchain) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001680 // TODO: Validate cases of re-creating a swapchain (the current code
1681 // assumes a new swapchain is being created).
Dustin Graves080069b2016-04-05 13:48:15 -06001682 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001683 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1684 char fn[] = "vkCreateSwapchainKHR";
Ian Elliott77f46ca2016-05-05 14:10:49 -06001685 SwpDevice *pDevice = NULL;
1686 {
1687 auto it = my_data->deviceMap.find(device);
1688 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1689 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001690
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001691 // Validate that the swapchain extension was enabled:
1692 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001693 return LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1694 "%s() called even though the %s extension was not enabled for this VkDevice.", fn,
1695 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001696 }
1697 if (!pCreateInfo) {
Ian Elliott432a3172016-05-09 12:33:47 -06001698 return LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001699 } else {
1700 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001701 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001702 "VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR");
1703 }
1704 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001705 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001706 }
1707 }
1708 if (!pSwapchain) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001709 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchain");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001710 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001711
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001712 // Keep around a useful pointer to pPhysicalDevice:
1713 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001714
Mark Lobodzinskid40b2db2016-02-25 13:56:57 -07001715 // Validate pCreateInfo values with result of
1716 // vkGetPhysicalDeviceQueueFamilyProperties
1717 if (pPhysicalDevice && pPhysicalDevice->gotQueueFamilyPropertyCount) {
Michael Mc Donnell75ecdb72016-04-03 14:47:51 -07001718 for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001719 if (pCreateInfo->pQueueFamilyIndices[i] >= pPhysicalDevice->numOfQueueFamilies) {
1720 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
1721 "VkPhysicalDevice", pCreateInfo->pQueueFamilyIndices[i],
1722 pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinskid40b2db2016-02-25 13:56:57 -07001723 }
1724 }
1725 }
1726
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001727 // Validate pCreateInfo values with the results of
1728 // vkGetPhysicalDeviceSurfaceCapabilitiesKHR():
1729 if (!pPhysicalDevice || !pPhysicalDevice->gotSurfaceCapabilities) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001730 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001731 "%s() called before calling "
1732 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1733 fn);
1734 } else if (pCreateInfo) {
1735 // Validate pCreateInfo->surface to make sure that
1736 // vkGetPhysicalDeviceSurfaceSupportKHR() reported this as a supported
1737 // surface:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001738 SwpSurface *pSurface = ((pPhysicalDevice) ? pPhysicalDevice->supportedSurfaces[pCreateInfo->surface] : NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001739 if (!pSurface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001740 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001741 "%s() called with pCreateInfo->surface that "
1742 "was not returned by "
1743 "vkGetPhysicalDeviceSurfaceSupportKHR() "
1744 "for the device.",
1745 fn);
1746 }
Ian Elliott4f147fc2016-01-20 08:52:08 -07001747
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001748 // Validate pCreateInfo->minImageCount against
1749 // VkSurfaceCapabilitiesKHR::{min|max}ImageCount:
1750 VkSurfaceCapabilitiesKHR *pCapabilities = &pPhysicalDevice->surfaceCapabilities;
1751 if ((pCreateInfo->minImageCount < pCapabilities->minImageCount) ||
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001752 ((pCapabilities->maxImageCount > 0) && (pCreateInfo->minImageCount > pCapabilities->maxImageCount))) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001753 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001754 SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT, "%s() called with pCreateInfo->minImageCount "
1755 "= %d, which is outside the bounds returned "
1756 "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. "
1757 "minImageCount = %d, maxImageCount = %d).",
1758 fn, pCreateInfo->minImageCount, pCapabilities->minImageCount, pCapabilities->maxImageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001759 }
1760 // Validate pCreateInfo->imageExtent against
1761 // VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
1762 if ((pCapabilities->currentExtent.width == -1) &&
1763 ((pCreateInfo->imageExtent.width < pCapabilities->minImageExtent.width) ||
1764 (pCreateInfo->imageExtent.width > pCapabilities->maxImageExtent.width) ||
1765 (pCreateInfo->imageExtent.height < pCapabilities->minImageExtent.height) ||
1766 (pCreateInfo->imageExtent.height > pCapabilities->maxImageExtent.height))) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001767 skipCall |= LOG_ERROR(
1768 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS,
1769 "%s() called with pCreateInfo->imageExtent = "
1770 "(%d,%d), which is outside the bounds "
1771 "returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): "
1772 "currentExtent = (%d,%d), minImageExtent = "
1773 "(%d,%d), maxImageExtent = (%d,%d).",
1774 fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, pCapabilities->currentExtent.width,
1775 pCapabilities->currentExtent.height, pCapabilities->minImageExtent.width, pCapabilities->minImageExtent.height,
1776 pCapabilities->maxImageExtent.width, pCapabilities->maxImageExtent.height);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001777 }
1778 if ((pCapabilities->currentExtent.width != -1) &&
1779 ((pCreateInfo->imageExtent.width != pCapabilities->currentExtent.width) ||
1780 (pCreateInfo->imageExtent.height != pCapabilities->currentExtent.height))) {
1781 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001782 SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN, "%s() called with pCreateInfo->imageExtent = "
1783 "(%d,%d), which is not equal to the "
1784 "currentExtent = (%d,%d) returned by "
1785 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1786 fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height,
1787 pCapabilities->currentExtent.width, pCapabilities->currentExtent.height);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001788 }
1789 // Validate pCreateInfo->preTransform has one bit set (1st two
1790 // lines of if-statement), which bit is also set in
1791 // VkSurfaceCapabilitiesKHR::supportedTransforms (3rd line of if-statement):
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001792 if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) ||
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001793 !(pCreateInfo->preTransform & pCapabilities->supportedTransforms)) {
1794 // This is an error situation; one for which we'd like to give
1795 // the developer a helpful, multi-line error message. Build it
1796 // up a little at a time, and then log it:
1797 std::string errorString = "";
1798 char str[1024];
1799 // Here's the first part of the message:
1800 sprintf(str, "%s() called with a non-supported "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001801 "pCreateInfo->preTransform (i.e. %s). "
1802 "Supported values are:\n",
1803 fn, surfaceTransformStr(pCreateInfo->preTransform));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001804 errorString += str;
1805 for (int i = 0; i < 32; i++) {
1806 // Build up the rest of the message:
1807 if ((1 << i) & pCapabilities->supportedTransforms) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001808 const char *newStr = surfaceTransformStr((VkSurfaceTransformFlagBitsKHR)(1 << i));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001809 sprintf(str, " %s\n", newStr);
1810 errorString += str;
1811 }
1812 }
1813 // Log the message that we've built up:
Mark Lobodzinskia4cbbcd2016-05-24 15:44:50 -06001814 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1815 reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM, LAYER_NAME,
1816 "%s", errorString.c_str());
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001817 }
1818 // Validate pCreateInfo->compositeAlpha has one bit set (1st two
1819 // lines of if-statement), which bit is also set in
1820 // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha (3rd line of if-statement):
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001821 if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) ||
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001822 !((pCreateInfo->compositeAlpha) & pCapabilities->supportedCompositeAlpha)) {
1823 // This is an error situation; one for which we'd like to give
1824 // the developer a helpful, multi-line error message. Build it
1825 // up a little at a time, and then log it:
1826 std::string errorString = "";
1827 char str[1024];
1828 // Here's the first part of the message:
1829 sprintf(str, "%s() called with a non-supported "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001830 "pCreateInfo->compositeAlpha (i.e. %s). "
1831 "Supported values are:\n",
1832 fn, surfaceCompositeAlphaStr(pCreateInfo->compositeAlpha));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001833 errorString += str;
1834 for (int i = 0; i < 32; i++) {
1835 // Build up the rest of the message:
1836 if ((1 << i) & pCapabilities->supportedCompositeAlpha) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001837 const char *newStr = surfaceCompositeAlphaStr((VkCompositeAlphaFlagBitsKHR)(1 << i));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001838 sprintf(str, " %s\n", newStr);
1839 errorString += str;
1840 }
1841 }
1842 // Log the message that we've built up:
Mark Lobodzinskia4cbbcd2016-05-24 15:44:50 -06001843 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1844 reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA,
1845 LAYER_NAME, "%s", errorString.c_str());
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001846 }
David McFarlande22cfb02016-05-20 18:26:28 -03001847 // Validate pCreateInfo->imageArrayLayers against
1848 // VkSurfaceCapabilitiesKHR::maxImageArrayLayers:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001849 if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > pCapabilities->maxImageArrayLayers)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001850 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
David McFarlande22cfb02016-05-20 18:26:28 -03001851 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_LAYERS, "%s() called with a non-supported "
1852 "pCreateInfo->imageArrayLayers (i.e. %d). "
1853 "Minimum value is 1, maximum value is %d.",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001854 fn, pCreateInfo->imageArrayLayers, pCapabilities->maxImageArrayLayers);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001855 }
1856 // Validate pCreateInfo->imageUsage against
1857 // VkSurfaceCapabilitiesKHR::supportedUsageFlags:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001858 if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & pCapabilities->supportedUsageFlags)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001859 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001860 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS, "%s() called with a non-supported "
1861 "pCreateInfo->imageUsage (i.e. 0x%08x)."
1862 " Supported flag bits are 0x%08x.",
1863 fn, pCreateInfo->imageUsage, pCapabilities->supportedUsageFlags);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001864 }
1865 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001866
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001867 // Validate pCreateInfo values with the results of
1868 // vkGetPhysicalDeviceSurfaceFormatsKHR():
1869 if (!pPhysicalDevice || !pPhysicalDevice->surfaceFormatCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001870 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001871 "%s() called before calling "
1872 "vkGetPhysicalDeviceSurfaceFormatsKHR().",
1873 fn);
1874 } else if (pCreateInfo) {
1875 // Validate pCreateInfo->imageFormat against
1876 // VkSurfaceFormatKHR::format:
1877 bool foundFormat = false;
1878 bool foundColorSpace = false;
1879 bool foundMatch = false;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001880 for (uint32_t i = 0; i < pPhysicalDevice->surfaceFormatCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001881 if (pCreateInfo->imageFormat == pPhysicalDevice->pSurfaceFormats[i].format) {
1882 // Validate pCreateInfo->imageColorSpace against
1883 // VkSurfaceFormatKHR::colorSpace:
1884 foundFormat = true;
1885 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1886 foundMatch = true;
1887 break;
1888 }
1889 } else {
1890 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1891 foundColorSpace = true;
1892 }
1893 }
1894 }
1895 if (!foundMatch) {
1896 if (!foundFormat) {
1897 if (!foundColorSpace) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001898 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1899 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP, "%s() called with neither a "
1900 "supported pCreateInfo->imageFormat "
1901 "(i.e. %d) nor a supported "
1902 "pCreateInfo->imageColorSpace "
1903 "(i.e. %d).",
1904 fn, pCreateInfo->imageFormat, pCreateInfo->imageColorSpace);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001905 } else {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001906 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1907 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT, "%s() called with a non-supported "
1908 "pCreateInfo->imageFormat (i.e. %d).",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001909 fn, pCreateInfo->imageFormat);
1910 }
1911 } else if (!foundColorSpace) {
1912 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001913 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE, "%s() called with a non-supported "
1914 "pCreateInfo->imageColorSpace (i.e. %d).",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001915 fn, pCreateInfo->imageColorSpace);
1916 }
1917 }
1918 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001919
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001920 // Validate pCreateInfo values with the results of
1921 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1922 if (!pPhysicalDevice || !pPhysicalDevice->presentModeCount) {
szdarkhackfb287d32016-03-12 18:41:19 +02001923 if (!pCreateInfo || (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR)) {
1924 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
1925 "%s() called before calling "
1926 "vkGetPhysicalDeviceSurfacePresentModesKHR().",
1927 fn);
1928 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001929 } else if (pCreateInfo) {
1930 // Validate pCreateInfo->presentMode against
1931 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1932 bool foundMatch = false;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001933 for (uint32_t i = 0; i < pPhysicalDevice->presentModeCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001934 if (pPhysicalDevice->pPresentModes[i] == pCreateInfo->presentMode) {
1935 foundMatch = true;
1936 break;
1937 }
1938 }
1939 if (!foundMatch) {
1940 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001941 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE, "%s() called with a non-supported "
1942 "pCreateInfo->presentMode (i.e. %s).",
1943 fn, presentModeStr(pCreateInfo->presentMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001944 }
1945 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001946
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001947 // Validate pCreateInfo->imageSharingMode and related values:
1948 if (pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001949 if ((pCreateInfo->queueFamilyIndexCount <= 1) || !pCreateInfo->pQueueFamilyIndices) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001950 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001951 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_VALUES, "%s() called with a supported "
baldurk209ccda2016-05-05 16:31:05 +02001952 "pCreateInfo->sharingMode of (i.e. %s), "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001953 "but with a bad value(s) for "
1954 "pCreateInfo->queueFamilyIndexCount or "
1955 "pCreateInfo->pQueueFamilyIndices).",
1956 fn, sharingModeStr(pCreateInfo->imageSharingMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001957 }
1958 } else if (pCreateInfo->imageSharingMode != VK_SHARING_MODE_EXCLUSIVE) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001959 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 -07001960 "%s() called with a non-supported "
1961 "pCreateInfo->imageSharingMode (i.e. %s).",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001962 fn, sharingModeStr(pCreateInfo->imageSharingMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001963 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001964
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001965 // Validate pCreateInfo->clipped:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001966 if (pCreateInfo && (pCreateInfo->clipped != VK_FALSE) && (pCreateInfo->clipped != VK_TRUE)) {
1967 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_BAD_BOOL,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001968 "%s() called with a VkBool32 value that is "
1969 "neither VK_TRUE nor VK_FALSE, but has the "
1970 "numeric value of %d.",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001971 fn, pCreateInfo->clipped);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001972 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001973
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001974 // Validate pCreateInfo->oldSwapchain:
1975 if (pCreateInfo && pCreateInfo->oldSwapchain) {
Ian Elliott77f46ca2016-05-05 14:10:49 -06001976 SwpSwapchain *pOldSwapchain = NULL;
1977 {
1978 auto it = my_data->swapchainMap.find(pCreateInfo->oldSwapchain);
1979 pOldSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1980 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001981 if (pOldSwapchain) {
1982 if (device != pOldSwapchain->pDevice->device) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001983 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1984 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE, "%s() called with a different VkDevice "
1985 "than the VkSwapchainKHR was created with.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001986 __FUNCTION__);
1987 }
1988 if (pCreateInfo->surface != pOldSwapchain->pSurface->surface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001989 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1990 SWAPCHAIN_CREATE_SWAP_DIFF_SURFACE, "%s() called with pCreateInfo->oldSwapchain "
1991 "that has a different VkSurfaceKHR than "
1992 "pCreateInfo->surface.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001993 fn);
1994 }
1995 } else {
1996 // TBD: Leave this in (not sure object_track will check this)?
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001997 skipCall |=
1998 LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pCreateInfo->oldSwapchain, "VkSwapchainKHR");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001999 }
2000 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002001
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002002 return skipCall;
2003}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002004
Chia-I Wufccbfe42016-04-28 14:01:30 +08002005VKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
2006 const VkAllocationCallbacks *pAllocator,
2007 VkSwapchainKHR *pSwapchain) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002008 VkResult result = VK_SUCCESS;
2009 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002010 std::unique_lock<std::mutex> lock(global_lock);
Dustin Graves080069b2016-04-05 13:48:15 -06002011 bool skipCall = validateCreateSwapchainKHR(device, pCreateInfo, pSwapchain);
Ian Elliott970a2bd2016-06-21 11:08:43 -06002012 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002013
Dustin Graves080069b2016-04-05 13:48:15 -06002014 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002015 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002016 result = my_data->device_dispatch_table->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002017 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002018
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002019 if (result == VK_SUCCESS) {
2020 // Remember the swapchain's handle, and link it to the device:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002021 SwpDevice *pDevice = NULL;
2022 {
2023 auto it = my_data->deviceMap.find(device);
2024 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2025 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002026
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002027 my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
2028 if (pDevice) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002029 pDevice->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002030 }
2031 my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
2032 my_data->swapchainMap[*pSwapchain].imageCount = 0;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002033 my_data->swapchainMap[*pSwapchain].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002034 // Store a pointer to the surface
2035 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002036 SwpInstance *pInstance = (pPhysicalDevice) ? pPhysicalDevice->pInstance : NULL;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002037 layer_data *my_instance_data =
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002038 ((pInstance) ? get_my_data_ptr(get_dispatch_key(pInstance->instance), layer_data_map) : NULL);
2039 SwpSurface *pSurface = ((my_data && pCreateInfo) ? &my_instance_data->surfaceMap[pCreateInfo->surface] : NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002040 my_data->swapchainMap[*pSwapchain].pSurface = pSurface;
2041 if (pSurface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002042 pSurface->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002043 }
2044 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002045 lock.unlock();
2046
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002047 return result;
2048 }
2049 return VK_ERROR_VALIDATION_FAILED_EXT;
2050}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002051
Chia-I Wufccbfe42016-04-28 14:01:30 +08002052VKAPI_ATTR void VKAPI_CALL
2053DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002054 // TODOs:
2055 //
2056 // - Implement a check for validity language that reads: All uses of
Ian Elliotta5d13a92016-04-07 09:05:45 -06002057 // presentable images acquired from pname:swapchain must: have completed
2058 // execution
Dustin Graves080069b2016-04-05 13:48:15 -06002059 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002060 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002061 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002062 SwpDevice *pDevice = NULL;
2063 {
2064 auto it = my_data->deviceMap.find(device);
2065 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2066 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07002067
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002068 // Validate that the swapchain extension was enabled:
2069 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002070 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2071 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2072 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002073 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002074
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002075 // Regardless of skipCall value, do some internal cleanup:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002076 SwpSwapchain *pSwapchain = NULL;
2077 {
2078 auto it = my_data->swapchainMap.find(swapchain);
2079 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2080 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002081 if (pSwapchain) {
2082 // Delete the SwpSwapchain associated with this swapchain:
2083 if (pSwapchain->pDevice) {
2084 pSwapchain->pDevice->swapchains.erase(swapchain);
2085 if (device != pSwapchain->pDevice->device) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002086 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002087 "%s() called with a different VkDevice than the "
2088 "VkSwapchainKHR was created with.",
2089 __FUNCTION__);
2090 }
2091 }
2092 if (pSwapchain->pSurface) {
2093 pSwapchain->pSurface->swapchains.erase(swapchain);
2094 }
2095 if (pSwapchain->imageCount) {
2096 pSwapchain->images.clear();
2097 }
2098 if ((pAllocator != NULL) != pSwapchain->usedAllocatorToCreate) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002099 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002100 "%s() called with incompatible pAllocator from when "
2101 "the object was created.",
2102 __FUNCTION__);
2103 }
2104 my_data->swapchainMap.erase(swapchain);
2105 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002106 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002107
Dustin Graves080069b2016-04-05 13:48:15 -06002108 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002109 // Call down the call chain:
2110 my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator);
2111 }
2112}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002113
Chia-I Wufccbfe42016-04-28 14:01:30 +08002114VKAPI_ATTR VkResult VKAPI_CALL
2115GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002116 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06002117 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002118 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002119 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002120 SwpDevice *pDevice = NULL;
2121 {
2122 auto it = my_data->deviceMap.find(device);
2123 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2124 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07002125
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002126 // Validate that the swapchain extension was enabled:
2127 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002128 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2129 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2130 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002131 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06002132 SwpSwapchain *pSwapchain = NULL;
2133 {
2134 auto it = my_data->swapchainMap.find(swapchain);
2135 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2136 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002137 if (!pSwapchainImageCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002138 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchainImageCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06002139 } else if (pSwapchain && pSwapchainImages) {
2140 // Compare the preliminary value of *pSwapchainImageCount with the
2141 // value this time:
2142 if (pSwapchain->imageCount == 0) {
2143 // Since we haven't recorded a preliminary value of
2144 // *pSwapchainImageCount, that likely means that the application
2145 // didn't previously call this function with a NULL value of
2146 // pSwapchainImages:
2147 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
2148 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2149 device, "pSwapchainImageCount", "pSwapchainImages");
2150 } else if (*pSwapchainImageCount > pSwapchain->imageCount) {
2151 skipCall |= LOG_ERROR_INVALID_COUNT(
2152 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2153 device, "pSwapchainImageCount", "pSwapchainImages",
2154 *pSwapchainImageCount, pSwapchain->imageCount);
2155 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002156 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002157 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002158
Dustin Graves080069b2016-04-05 13:48:15 -06002159 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002160 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002161 result = my_data->device_dispatch_table->GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002162 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002163
Ian Elliott32311832016-02-04 08:17:18 -07002164 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002165 {
2166 auto it = my_data->swapchainMap.find(swapchain);
2167 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2168 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002169 if ((result == VK_SUCCESS) && pSwapchain && !pSwapchainImages && pSwapchainImageCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002170 // Record the result of this preliminary query:
2171 pSwapchain->imageCount = *pSwapchainImageCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06002172 } else if ((result == VK_SUCCESS) && pSwapchain && pSwapchainImages &&
2173 pSwapchainImageCount && (*pSwapchainImageCount > 0)) {
2174 // Record the images and their state:
2175 pSwapchain->imageCount = *pSwapchainImageCount;
2176 for (uint32_t i = 0; i < *pSwapchainImageCount; i++) {
2177 pSwapchain->images[i].image = pSwapchainImages[i];
2178 pSwapchain->images[i].pSwapchain = pSwapchain;
2179 pSwapchain->images[i].acquiredByApp = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002180 }
2181 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002182 lock.unlock();
2183
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002184 return result;
2185 }
2186 return VK_ERROR_VALIDATION_FAILED_EXT;
2187}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002188
Chia-I Wufccbfe42016-04-28 14:01:30 +08002189VKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
2190 VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002191 // TODOs:
2192 //
2193 // - Address the timeout. Possibilities include looking at the state of the
2194 // swapchain's images, depending on the timeout value.
2195 // - Implement a check for validity language that reads: If pname:semaphore is
2196 // not sname:VK_NULL_HANDLE it must: be unsignalled
2197 // - Implement a check for validity language that reads: If pname:fence is not
2198 // sname:VK_NULL_HANDLE it must: be unsignalled and mustnot: be associated
2199 // with any other queue command that has not yet completed execution on that
2200 // queue
2201 // - Record/update the state of the swapchain, in case an error occurs
2202 // (e.g. VK_ERROR_OUT_OF_DATE_KHR).
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002203 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06002204 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002205 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002206 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002207 SwpDevice *pDevice = NULL;
2208 {
2209 auto it = my_data->deviceMap.find(device);
2210 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2211 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07002212
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002213 // Validate that the swapchain extension was enabled:
2214 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002215 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2216 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2217 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002218 }
Ian Elliottfa8f0322016-03-23 08:28:54 -06002219 if ((semaphore == VK_NULL_HANDLE) && (fence == VK_NULL_HANDLE)) {
Ian Elliott5da0c962016-03-23 11:13:09 -06002220 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_NO_SYNC_FOR_ACQUIRE,
2221 "%s() called with both the semaphore and fence parameters set to "
Jamie Madillcc4e9322016-05-04 12:20:15 -07002222 "VK_NULL_HANDLE (at least one should be used).", __FUNCTION__);
Ian Elliottfa8f0322016-03-23 08:28:54 -06002223 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06002224 SwpSwapchain *pSwapchain = NULL;
2225 {
2226 auto it = my_data->swapchainMap.find(swapchain);
2227 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2228 }
Ian Elliott5c680282016-04-06 14:29:56 -06002229 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
2230 if (pSwapchain && pPhysicalDevice && pPhysicalDevice->gotSurfaceCapabilities) {
2231 // Look to see if the application has already acquired the maximum
2232 // number of images, and this will push it past the spec-defined
2233 // limits:
2234 uint32_t minImageCount = pPhysicalDevice->surfaceCapabilities.minImageCount;
2235 uint32_t imagesAcquiredByApp = 0;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002236 for (uint32_t i = 0; i < pSwapchain->imageCount; i++) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002237 if (pSwapchain->images[i].acquiredByApp) {
Ian Elliott5c680282016-04-06 14:29:56 -06002238 imagesAcquiredByApp++;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002239 }
2240 }
Ian Elliott5c680282016-04-06 14:29:56 -06002241 if (imagesAcquiredByApp > (pSwapchain->imageCount - minImageCount)) {
2242 skipCall |= LOG_ERROR(
2243 VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
2244 swapchain, "VkSwapchainKHR",
2245 SWAPCHAIN_APP_ACQUIRES_TOO_MANY_IMAGES,
2246 "%s() called when it cannot succeed. The application has "
2247 "acquired %d image(s) that have not yet been presented. The "
2248 "maximum number of images that the application can "
2249 "simultaneously acquire from this swapchain (including this "
2250 "call to %s()) is %d. That value is derived by subtracting "
2251 "VkSurfaceCapabilitiesKHR::minImageCount (%d) from the number "
2252 "of images in the swapchain (%d) and adding 1.\n",
2253 __FUNCTION__, imagesAcquiredByApp, __FUNCTION__,
2254 (pSwapchain->imageCount - minImageCount + 1),
2255 minImageCount, pSwapchain->imageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002256 }
2257 }
2258 if (!pImageIndex) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002259 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pImageIndex");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002260 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002261 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002262
Dustin Graves080069b2016-04-05 13:48:15 -06002263 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002264 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002265 result = my_data->device_dispatch_table->AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002266 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002267
Ian Elliott32311832016-02-04 08:17:18 -07002268 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002269 {
2270 auto it = my_data->swapchainMap.find(swapchain);
2271 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2272 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002273 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) && pSwapchain) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002274 // Change the state of the image (now acquired by the application):
2275 pSwapchain->images[*pImageIndex].acquiredByApp = true;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002276 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002277 lock.unlock();
2278
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002279 return result;
2280 }
2281 return VK_ERROR_VALIDATION_FAILED_EXT;
2282}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002283
Chia-I Wufccbfe42016-04-28 14:01:30 +08002284VKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002285 // TODOs:
2286 //
2287 // - Implement a check for validity language that reads: Any given element of
2288 // sname:VkSemaphore in pname:pWaitSemaphores must: refer to a prior signal
2289 // of that sname:VkSemaphore that won't be consumed by any other wait on that
2290 // semaphore
2291 // - Record/update the state of the swapchain, in case an error occurs
2292 // (e.g. VK_ERROR_OUT_OF_DATE_KHR).
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002293 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06002294 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002295 layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002296
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002297 if (!pPresentInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002298 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002299 } else {
2300 if (pPresentInfo->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002301 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002302 "VK_STRUCTURE_TYPE_PRESENT_INFO_KHR");
2303 }
2304 if (pPresentInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002305 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002306 }
2307 if (!pPresentInfo->swapchainCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002308 skipCall |= LOG_ERROR_ZERO_VALUE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->swapchainCount");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002309 }
2310 if (!pPresentInfo->pSwapchains) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002311 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pSwapchains");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002312 }
2313 if (!pPresentInfo->pImageIndices) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002314 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pImageIndices");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002315 }
2316 // Note: pPresentInfo->pResults is allowed to be NULL
2317 }
Ian Elliott046ed2c2015-12-30 17:07:17 -07002318
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002319 std::unique_lock<std::mutex> lock(global_lock);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002320 for (uint32_t i = 0; pPresentInfo && (i < pPresentInfo->swapchainCount); i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002321 uint32_t index = pPresentInfo->pImageIndices[i];
Ian Elliott77f46ca2016-05-05 14:10:49 -06002322 SwpSwapchain *pSwapchain = NULL;
2323 {
2324 auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
2325 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2326 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002327 if (pSwapchain) {
2328 if (!pSwapchain->pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002329 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, pSwapchain->pDevice, "VkDevice",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002330 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002331 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2332 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002333 }
2334 if (index >= pSwapchain->imageCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002335 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
2336 SWAPCHAIN_INDEX_TOO_LARGE, "%s() called for an index that is too "
2337 "large (i.e. %d). There are only %d "
2338 "images in this VkSwapchainKHR.\n",
2339 __FUNCTION__, index, pSwapchain->imageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002340 } else {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002341 if (!pSwapchain->images[index].acquiredByApp) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002342 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i],
2343 "VkSwapchainKHR", SWAPCHAIN_INDEX_NOT_IN_USE, "%s() returned an index (i.e. %d) "
Ian Elliotta5d13a92016-04-07 09:05:45 -06002344 "for an image that is not acquired by "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002345 "the application.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002346 __FUNCTION__, index);
2347 }
2348 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06002349 SwpQueue *pQueue = NULL;
2350 {
2351 auto it = my_data->queueMap.find(queue);
2352 pQueue = (it == my_data->queueMap.end()) ? NULL : &it->second;
2353 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002354 SwpSurface *pSurface = pSwapchain->pSurface;
2355 if (pQueue && pSurface && pSurface->numQueueFamilyIndexSupport) {
2356 uint32_t queueFamilyIndex = pQueue->queueFamilyIndex;
2357 // Note: the 1st test is to ensure queueFamilyIndex is in range,
2358 // and the 2nd test is the validation check:
2359 if ((pSurface->numQueueFamilyIndexSupport > queueFamilyIndex) &&
2360 (!pSurface->pQueueFamilyIndexSupport[queueFamilyIndex])) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002361 skipCall |=
2362 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
2363 SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, "%s() called with a swapchain whose "
2364 "surface is not supported for "
2365 "presention on this device with the "
2366 "queueFamilyIndex (i.e. %d) of the "
2367 "given queue.",
2368 __FUNCTION__, queueFamilyIndex);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002369 }
2370 }
2371 }
2372 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002373 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002374
Dustin Graves080069b2016-04-05 13:48:15 -06002375 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002376 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002377 result = my_data->device_dispatch_table->QueuePresentKHR(queue, pPresentInfo);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002378 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002379
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002380 if (pPresentInfo && ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR))) {
2381 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002382 int index = pPresentInfo->pImageIndices[i];
Ian Elliott77f46ca2016-05-05 14:10:49 -06002383 SwpSwapchain *pSwapchain = NULL;
2384 {
2385 auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
2386 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2387 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002388 if (pSwapchain) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002389 // Change the state of the image (no longer acquired by the
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002390 // application):
Ian Elliotta5d13a92016-04-07 09:05:45 -06002391 pSwapchain->images[index].acquiredByApp = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002392 }
2393 }
2394 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002395 lock.unlock();
2396
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002397 return result;
2398 }
2399 return VK_ERROR_VALIDATION_FAILED_EXT;
2400}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002401
Chia-I Wufccbfe42016-04-28 14:01:30 +08002402VKAPI_ATTR void VKAPI_CALL
2403GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
Dustin Graves080069b2016-04-05 13:48:15 -06002404 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002405 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliottc4db6952016-01-21 14:29:45 -07002406
Dustin Graves080069b2016-04-05 13:48:15 -06002407 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002408 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002409 my_data->device_dispatch_table->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
Ian Elliottc4db6952016-01-21 14:29:45 -07002410
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002411 // Remember the queue's handle, and link it to the device:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002412 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002413 SwpDevice *pDevice = NULL;
2414 {
2415 auto it = my_data->deviceMap.find(device);
2416 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2417 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002418 my_data->queueMap[&pQueue].queue = *pQueue;
2419 if (pDevice) {
2420 pDevice->queues[*pQueue] = &my_data->queueMap[*pQueue];
2421 }
2422 my_data->queueMap[&pQueue].pDevice = pDevice;
2423 my_data->queueMap[&pQueue].queueFamilyIndex = queueFamilyIndex;
2424 }
2425}
Ian Elliottc4db6952016-01-21 14:29:45 -07002426
Chia-I Wufccbfe42016-04-28 14:01:30 +08002427VKAPI_ATTR VkResult VKAPI_CALL
2428CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2429 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002430 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002431 VkResult result =
2432 my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002433 if (VK_SUCCESS == result) {
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002434 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -06002435 result = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002436 }
2437 return result;
2438}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002439
Chia-I Wufccbfe42016-04-28 14:01:30 +08002440VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance,
2441 VkDebugReportCallbackEXT msgCallback,
2442 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002443 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2444 my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002445 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002446 layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
2447}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002448
Chia-I Wufccbfe42016-04-28 14:01:30 +08002449VKAPI_ATTR void VKAPI_CALL
2450DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
2451 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002452 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002453 my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix,
2454 pMsg);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002455}
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07002456
Chia-I Wub02600c2016-05-20 07:11:22 +08002457VKAPI_ATTR VkResult VKAPI_CALL
2458EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
2459 return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
2460}
2461
2462VKAPI_ATTR VkResult VKAPI_CALL
2463EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
2464 return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
2465}
2466
2467VKAPI_ATTR VkResult VKAPI_CALL
2468EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
2469 if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
2470 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
2471
2472 return VK_ERROR_LAYER_NOT_PRESENT;
2473}
2474
Chia-I Wufccbfe42016-04-28 14:01:30 +08002475VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
2476 const char *pLayerName, uint32_t *pCount,
2477 VkExtensionProperties *pProperties) {
Chia-I Wu2b481252016-04-28 14:21:13 +08002478 if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
Chia-I Wu045209e2016-04-28 11:21:49 +08002479 return util_GetExtensionProperties(0, nullptr, pCount, pProperties);
Chia-I Wu2b481252016-04-28 14:21:13 +08002480
2481 assert(physicalDevice);
2482
2483 dispatch_key key = get_dispatch_key(physicalDevice);
2484 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
2485 return my_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002486}
2487
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002488static PFN_vkVoidFunction
Chia-I Wu22813c72016-04-28 14:38:57 +08002489intercept_core_instance_command(const char *name);
2490
2491static PFN_vkVoidFunction
2492intercept_khr_surface_command(const char *name, VkInstance instance);
2493
2494static PFN_vkVoidFunction
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002495intercept_core_device_command(const char *name);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002496
Chia-I Wu83245952016-05-05 16:13:19 +08002497static PFN_vkVoidFunction
2498intercept_khr_swapchain_command(const char *name, VkDevice dev);
2499
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002500VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
2501 PFN_vkVoidFunction proc = intercept_core_device_command(funcName);
2502 if (proc)
2503 return proc;
2504
2505 assert(device);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002506
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002507 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06002508
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002509 my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Courtney Goeltzenleuchter1e9e6c82016-03-19 10:38:52 -06002510 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
Chia-I Wu83245952016-05-05 16:13:19 +08002511
2512 proc = intercept_khr_swapchain_command(funcName, device);
2513 if (proc)
2514 return proc;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002515
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002516 if (pDisp->GetDeviceProcAddr == NULL)
2517 return NULL;
2518 return pDisp->GetDeviceProcAddr(device, funcName);
2519}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002520
Chia-I Wufccbfe42016-04-28 14:01:30 +08002521VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wu22813c72016-04-28 14:38:57 +08002522 PFN_vkVoidFunction proc = intercept_core_instance_command(funcName);
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002523 if (!proc)
2524 proc = intercept_core_device_command(funcName);
2525 if (!proc)
2526 proc = intercept_khr_swapchain_command(funcName, VK_NULL_HANDLE);
Chia-I Wu22813c72016-04-28 14:38:57 +08002527 if (proc)
2528 return proc;
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07002529
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002530 assert(instance);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002531
2532 layer_data *my_data;
2533 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002534 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Ian Elliott68124ac2015-10-07 16:18:35 -06002535
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002536 proc = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
2537 if (!proc)
2538 proc = intercept_khr_surface_command(funcName, instance);
Chia-I Wu22813c72016-04-28 14:38:57 +08002539 if (proc)
2540 return proc;
Ian Elliott0b4d6242015-09-22 10:51:24 -06002541
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002542 if (pTable->GetInstanceProcAddr == NULL)
2543 return NULL;
2544 return pTable->GetInstanceProcAddr(instance, funcName);
2545}
Chia-I Wu045209e2016-04-28 11:21:49 +08002546
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002547static PFN_vkVoidFunction
Chia-I Wu22813c72016-04-28 14:38:57 +08002548intercept_core_instance_command(const char *name) {
2549 static const struct {
2550 const char *name;
2551 PFN_vkVoidFunction proc;
2552 } core_instance_commands[] = {
2553 { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
2554 { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
2555 { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) },
2556 { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
2557 { "vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices) },
Chia-I Wub02600c2016-05-20 07:11:22 +08002558 { "vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties) },
2559 { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
2560 { "vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties) },
Chia-I Wu22813c72016-04-28 14:38:57 +08002561 { "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
2562 { "vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties) },
2563 };
2564
2565 for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
2566 if (!strcmp(core_instance_commands[i].name, name))
2567 return core_instance_commands[i].proc;
2568 }
2569
2570 return nullptr;
2571}
2572
2573static PFN_vkVoidFunction
2574intercept_khr_surface_command(const char *name, VkInstance instance) {
2575 static const struct {
2576 const char *name;
2577 PFN_vkVoidFunction proc;
2578 } khr_surface_commands[] = {
2579#ifdef VK_USE_PLATFORM_ANDROID_KHR
2580 { "vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateAndroidSurfaceKHR) },
2581#endif // VK_USE_PLATFORM_ANDROID_KHR
2582#ifdef VK_USE_PLATFORM_MIR_KHR
2583 { "vkCreateMirSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateMirSurfaceKHR) },
2584 { "vkGetPhysicalDeviceMirPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceMirPresentationSupportKHR) },
2585#endif // VK_USE_PLATFORM_MIR_KHR
2586#ifdef VK_USE_PLATFORM_WAYLAND_KHR
2587 { "vkCreateWaylandSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWaylandSurfaceKHR) },
2588 { "vkGetPhysicalDeviceWaylandPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWaylandPresentationSupportKHR) },
2589#endif // VK_USE_PLATFORM_WAYLAND_KHR
2590#ifdef VK_USE_PLATFORM_WIN32_KHR
2591 { "vkCreateWin32SurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWin32SurfaceKHR) },
2592 { "vkGetPhysicalDeviceWin32PresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWin32PresentationSupportKHR) },
2593#endif // VK_USE_PLATFORM_WIN32_KHR
2594#ifdef VK_USE_PLATFORM_XCB_KHR
2595 { "vkCreateXcbSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXcbSurfaceKHR) },
2596 { "vkGetPhysicalDeviceXcbPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXcbPresentationSupportKHR) },
2597#endif // VK_USE_PLATFORM_XCB_KHR
2598#ifdef VK_USE_PLATFORM_XLIB_KHR
2599 { "vkCreateXlibSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXlibSurfaceKHR) },
2600 { "vkGetPhysicalDeviceXlibPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXlibPresentationSupportKHR) },
2601#endif // VK_USE_PLATFORM_XLIB_KHR
2602 { "vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySurfaceKHR) },
2603 { "vkGetPhysicalDeviceSurfaceSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceSupportKHR) },
2604 { "vkGetPhysicalDeviceSurfaceCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceCapabilitiesKHR) },
2605 { "vkGetPhysicalDeviceSurfaceFormatsKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceFormatsKHR) },
2606 { "vkGetPhysicalDeviceSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfacePresentModesKHR) },
Petros Bantolas2b40be72016-04-15 11:02:59 +01002607 { "vkGetPhysicalDeviceDisplayPropertiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceDisplayPropertiesKHR) },
2608 { "vkGetPhysicalDeviceDisplayPlanePropertiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceDisplayPlanePropertiesKHR) },
2609 { "vkGetDisplayPlaneSupportedDisplaysKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayPlaneSupportedDisplaysKHR) },
2610 { "vkGetDisplayModePropertiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayModePropertiesKHR) },
2611 { "vkCreateDisplayModeKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDisplayModeKHR) },
2612 { "vkGetDisplayPlaneCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayPlaneCapabilitiesKHR) },
2613 { "vkCreateDisplayPlaneSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDisplayPlaneSurfaceKHR) },
Chia-I Wu22813c72016-04-28 14:38:57 +08002614 };
2615
2616 // do not check if VK_KHR_*_surface is enabled (why?)
2617
2618 for (size_t i = 0; i < ARRAY_SIZE(khr_surface_commands); i++) {
2619 if (!strcmp(khr_surface_commands[i].name, name))
2620 return khr_surface_commands[i].proc;
2621 }
2622
2623 return nullptr;
2624}
2625
2626static PFN_vkVoidFunction
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002627intercept_core_device_command(const char *name) {
2628 static const struct {
2629 const char *name;
2630 PFN_vkVoidFunction proc;
2631 } core_device_commands[] = {
2632 { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
2633 { "vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice) },
2634 { "vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue) },
2635 };
2636
2637 for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) {
2638 if (!strcmp(core_device_commands[i].name, name))
2639 return core_device_commands[i].proc;
2640 }
2641
2642 return nullptr;
2643}
2644
Chia-I Wu83245952016-05-05 16:13:19 +08002645static PFN_vkVoidFunction
2646intercept_khr_swapchain_command(const char *name, VkDevice dev) {
2647 static const struct {
2648 const char *name;
2649 PFN_vkVoidFunction proc;
2650 } khr_swapchain_commands[] = {
2651 { "vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR) },
2652 { "vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR) },
2653 { "vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR) },
2654 { "vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR) },
2655 { "vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR) },
2656 };
2657
2658 // do not check if VK_KHR_swapchain is enabled (why?)
2659
2660 for (size_t i = 0; i < ARRAY_SIZE(khr_swapchain_commands); i++) {
2661 if (!strcmp(khr_swapchain_commands[i].name, name))
2662 return khr_swapchain_commands[i].proc;
2663 }
2664
2665 return nullptr;
2666}
2667
Chia-I Wu516b5082016-04-28 11:27:46 +08002668} // namespace swapchain
2669
2670// vk_layer_logging.h expects these to be defined
2671
Chia-I Wufccbfe42016-04-28 14:01:30 +08002672VKAPI_ATTR VkResult VKAPI_CALL
Chia-I Wu516b5082016-04-28 11:27:46 +08002673vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2674 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002675 return swapchain::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Chia-I Wu516b5082016-04-28 11:27:46 +08002676}
2677
Chia-I Wufccbfe42016-04-28 14:01:30 +08002678VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance,
Chia-I Wu516b5082016-04-28 11:27:46 +08002679 VkDebugReportCallbackEXT msgCallback,
2680 const VkAllocationCallbacks *pAllocator) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002681 swapchain::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Chia-I Wu516b5082016-04-28 11:27:46 +08002682}
2683
Chia-I Wufccbfe42016-04-28 14:01:30 +08002684VKAPI_ATTR void VKAPI_CALL
Chia-I Wu516b5082016-04-28 11:27:46 +08002685vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
2686 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002687 swapchain::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
Chia-I Wu516b5082016-04-28 11:27:46 +08002688}
2689
Chia-I Wub02600c2016-05-20 07:11:22 +08002690// loader-layer interface v0, just wrappers since there is only a layer
Chia-I Wu516b5082016-04-28 11:27:46 +08002691
Chia-I Wu045209e2016-04-28 11:21:49 +08002692VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2693vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002694 return swapchain::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002695}
2696
2697VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2698vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002699 return swapchain::EnumerateInstanceLayerProperties(pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002700}
2701
2702VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2703vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002704 // the layer command handles VK_NULL_HANDLE just fine internally
2705 assert(physicalDevice == VK_NULL_HANDLE);
2706 return swapchain::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
Chia-I Wu516b5082016-04-28 11:27:46 +08002707}
2708
2709VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
2710 const char *pLayerName, uint32_t *pCount,
2711 VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002712 // the layer command handles VK_NULL_HANDLE just fine internally
2713 assert(physicalDevice == VK_NULL_HANDLE);
Chia-I Wu2b481252016-04-28 14:21:13 +08002714 return swapchain::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
Chia-I Wu516b5082016-04-28 11:27:46 +08002715}
2716
2717VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002718 return swapchain::GetDeviceProcAddr(dev, funcName);
Chia-I Wu516b5082016-04-28 11:27:46 +08002719}
2720
2721VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002722 return swapchain::GetInstanceProcAddr(instance, funcName);
Chia-I Wu045209e2016-04-28 11:21:49 +08002723}