blob: 1488febe28665d1843810525b76b486c1b1c51ec [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
966static uint32_t gDisplayPlanePropertyCount = 0;
967static bool gDisplayPlanePropertyCountInit = false;
968VKAPI_ATTR VkResult VKAPI_CALL
969GetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkDisplayPlanePropertiesKHR *pProperties) {
970 VkResult result = VK_SUCCESS;
971 bool skipCall = false;
972 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
973 std::unique_lock<std::mutex> lock(global_lock);
974 SwpPhysicalDevice *pPhysicalDevice = NULL;
975 {
976 auto it = my_data->physicalDeviceMap.find(physicalDevice);
977 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
978 }
979
980 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
981 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
982 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
983 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
984 VK_KHR_DISPLAY_EXTENSION_NAME);
985 }
986
987 if (!pPropertyCount) {
988 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pPropertyCount");
989 }
990 lock.unlock();
991
992 if (!skipCall) {
993 result = my_data->instance_dispatch_table->GetPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, pPropertyCount, pProperties);
994
995 lock.lock();
996 if (!pPhysicalDevice->gotDisplayPlanePropertyCount)
997 {
998 pPhysicalDevice->displayPlanePropertyCount = *pPropertyCount;
999 pPhysicalDevice->gotDisplayPlanePropertyCount = true;
1000 }
1001 lock.unlock();
1002
1003 return result;
1004 }
1005 return VK_ERROR_VALIDATION_FAILED_EXT;
1006}
1007
1008VKAPI_ATTR VkResult VKAPI_CALL
1009GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays) {
1010 VkResult result = VK_SUCCESS;
1011 bool skipCall = false;
1012 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1013 std::unique_lock<std::mutex> lock(global_lock);
1014 SwpPhysicalDevice *pPhysicalDevice = NULL;
1015 {
1016 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1017 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1018 }
1019
1020 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
1021 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1022 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1023 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1024 VK_KHR_DISPLAY_EXTENSION_NAME);
1025 }
1026
1027 if (!pDisplayCount) {
1028 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pDisplayCount");
1029 }
1030
1031 if (!gDisplayPlanePropertyCountInit)
1032 {
1033 LOG_WARNING(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
1034 SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY,
1035 "Potential problem with calling %s() without first querying vkGetPhysicalDeviceDisplayPlanePropertiesKHR.",
1036 __FUNCTION__);
1037 }
1038
1039 if (gDisplayPlanePropertyCountInit && planeIndex >= gDisplayPlanePropertyCount)
1040 {
1041 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
1042 SWAPCHAIN_PLANE_INDEX_TOO_LARGE,
1043 "%s(): %s must be in the range [0, %d] that was returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR. Do you have the plane index hardcoded?",
1044 __FUNCTION__,
1045 "planeIndex",
1046 gDisplayPlanePropertyCount - 1);
1047 }
1048 lock.unlock();
1049
1050 if (!skipCall) {
1051 result = my_data->instance_dispatch_table->GetDisplayPlaneSupportedDisplaysKHR(physicalDevice, planeIndex, pDisplayCount, pDisplays);
1052
1053 return result;
1054 }
1055 return VK_ERROR_VALIDATION_FAILED_EXT;
1056}
1057
1058VKAPI_ATTR VkResult VKAPI_CALL
1059GetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties) {
1060 VkResult result = VK_SUCCESS;
1061 bool skipCall = false;
1062 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1063 std::unique_lock<std::mutex> lock(global_lock);
1064 SwpPhysicalDevice *pPhysicalDevice = NULL;
1065 {
1066 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1067 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1068 }
1069
1070 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
1071 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1072 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1073 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1074 VK_KHR_DISPLAY_EXTENSION_NAME);
1075 }
1076
1077 if (!pPropertyCount) {
1078 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pPropertyCount");
1079 }
1080 lock.unlock();
1081
1082 if (!skipCall) {
1083 result = my_data->instance_dispatch_table->GetDisplayModePropertiesKHR(physicalDevice, display, pPropertyCount, pProperties);
1084 return result;
1085 }
1086 return VK_ERROR_VALIDATION_FAILED_EXT;
1087}
1088
1089VKAPI_ATTR VkResult VKAPI_CALL
1090CreateDisplayModeKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode) {
1091 VkResult result = VK_SUCCESS;
1092 bool skipCall = false;
1093 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1094 std::unique_lock<std::mutex> lock(global_lock);
1095 SwpPhysicalDevice *pPhysicalDevice = NULL;
1096 {
1097 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1098 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1099 }
1100
1101 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
1102 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1103 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1104 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1105 VK_KHR_DISPLAY_EXTENSION_NAME);
1106 }
1107
1108 if (!pCreateInfo) {
1109 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pCreateInfo");
1110 }
1111 lock.unlock();
1112
1113 if (!skipCall) {
1114 result = my_data->instance_dispatch_table->CreateDisplayModeKHR(physicalDevice, display, pCreateInfo, pAllocator, pMode);
1115 return result;
1116 }
1117
1118 return VK_ERROR_VALIDATION_FAILED_EXT;
1119}
1120
1121VKAPI_ATTR VkResult VKAPI_CALL
1122GetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR* pCapabilities) {
1123 VkResult result = VK_SUCCESS;
1124 bool skipCall = false;
1125 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1126 std::unique_lock<std::mutex> lock(global_lock);
1127 SwpPhysicalDevice *pPhysicalDevice = NULL;
1128 {
1129 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1130 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1131 }
1132
1133 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
1134 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1135 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1136 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1137 VK_KHR_DISPLAY_EXTENSION_NAME);
1138 }
1139
1140 if (!gDisplayPlanePropertyCountInit)
1141 {
1142 LOG_WARNING(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
1143 SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY,
1144 "Potential problem with calling %s() without first querying vkGetPhysicalDeviceDisplayPlanePropertiesKHR.",
1145 __FUNCTION__);
1146 }
1147
1148 if (gDisplayPlanePropertyCountInit && planeIndex >= gDisplayPlanePropertyCount)
1149 {
1150 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
1151 SWAPCHAIN_PLANE_INDEX_TOO_LARGE,
1152 "%s(): %s must be in the range [0, %d] that was returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR. Do you have the plane index hardcoded?",
1153 __FUNCTION__,
1154 "planeIndex",
1155 gDisplayPlanePropertyCount - 1);
1156 }
1157
1158 if (!pCapabilities) {
1159 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pCapabilities");
1160 }
1161 lock.unlock();
1162
1163 if (!skipCall) {
1164 result = my_data->instance_dispatch_table->GetDisplayPlaneCapabilitiesKHR(physicalDevice, mode, planeIndex, pCapabilities);
1165 return result;
1166 }
1167
1168 return VK_ERROR_VALIDATION_FAILED_EXT;
1169}
1170
1171VKAPI_ATTR VkResult VKAPI_CALL
1172CreateDisplayPlaneSurfaceKHR(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
1173 VkSurfaceKHR *pSurface) {
1174 VkResult result = VK_SUCCESS;
1175 bool skipCall = false;
1176 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1177 std::unique_lock<std::mutex> lock(global_lock);
1178 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
1179
1180 // Validate that the platform extension was enabled:
1181 if (pInstance && !pInstance->displayExtensionEnabled) {
1182 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1183 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1184 VK_KHR_DISPLAY_EXTENSION_NAME);
1185 }
1186
1187 if (!pCreateInfo) {
1188 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
1189 } else {
1190 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR) {
1191 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
1192 "VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR");
1193 }
1194 if (pCreateInfo->pNext != NULL) {
1195 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
1196 }
1197 }
1198
1199 if (!skipCall) {
1200 // Call down the call chain:
1201 lock.unlock();
1202 result = my_data->instance_dispatch_table->CreateDisplayPlaneSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
1203 lock.lock();
1204
1205 // Obtain this pointer again after locking:
1206 pInstance = &(my_data->instanceMap[instance]);
1207 if ((result == VK_SUCCESS) && pInstance && pSurface) {
1208 // Record the VkSurfaceKHR returned by the ICD:
1209 my_data->surfaceMap[*pSurface].surface = *pSurface;
1210 my_data->surfaceMap[*pSurface].pInstance = pInstance;
1211 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
1212 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
1213 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
1214 // Point to the associated SwpInstance:
1215 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
1216 }
1217 lock.unlock();
1218 return result;
1219 }
1220 return VK_ERROR_VALIDATION_FAILED_EXT;
1221}
1222
Chia-I Wufccbfe42016-04-28 14:01:30 +08001223VKAPI_ATTR void VKAPI_CALL
1224DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) {
Dustin Graves080069b2016-04-05 13:48:15 -06001225 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001226 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001227 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001228 SwpSurface *pSurface = NULL;
1229 {
1230 auto it = my_data->surfaceMap.find(surface);
1231 pSurface = (it == my_data->surfaceMap.end()) ? NULL : &it->second;
1232 }
1233 SwpInstance *pInstance = NULL;
1234 {
1235 auto it = my_data->instanceMap.find(instance);
1236 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
1237 }
Ian Elliottf6b8c782016-04-29 13:03:17 -06001238
1239 // Validate that the platform extension was enabled:
1240 if (pInstance && !pInstance->surfaceExtensionEnabled) {
1241 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1242 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1243 VK_KHR_SURFACE_EXTENSION_NAME);
1244 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001245
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001246 // Regardless of skipCall value, do some internal cleanup:
1247 if (pSurface) {
1248 // Delete the SwpSurface associated with this surface:
1249 if (pSurface->pInstance) {
1250 pSurface->pInstance->surfaces.erase(surface);
1251 }
1252 if (!pSurface->swapchains.empty()) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001253 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001254 "%s() called before all of its associated "
1255 "VkSwapchainKHRs were destroyed.",
1256 __FUNCTION__);
1257 // Empty and then delete all SwpSwapchain's
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001258 for (auto it = pSurface->swapchains.begin(); it != pSurface->swapchains.end(); it++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001259 // Delete all SwpImage's
1260 it->second->images.clear();
1261 // In case the swapchain's device hasn't been destroyed yet
1262 // (which isn't likely, but is possible), delete its
1263 // association with this swapchain (i.e. so we can't point to
1264 // this swpchain from that device, later on):
1265 if (it->second->pDevice) {
1266 it->second->pDevice->swapchains.clear();
1267 }
1268 }
1269 pSurface->swapchains.clear();
1270 }
1271 if ((pAllocator != NULL) != pSurface->usedAllocatorToCreate) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001272 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001273 "%s() called with incompatible pAllocator from when "
1274 "the object was created.",
1275 __FUNCTION__);
1276 }
1277 my_data->surfaceMap.erase(surface);
1278 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001279 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001280
Dustin Graves080069b2016-04-05 13:48:15 -06001281 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001282 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001283 my_data->instance_dispatch_table->DestroySurfaceKHR(instance, surface, pAllocator);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001284 }
1285}
1286
Chia-I Wufccbfe42016-04-28 14:01:30 +08001287VKAPI_ATTR VkResult VKAPI_CALL
1288EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001289 VkResult result = VK_SUCCESS;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001290 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001291
1292 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001293 result = my_data->instance_dispatch_table->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
Ian Elliott32311832016-02-04 08:17:18 -07001294
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001295 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001296 SwpInstance *pInstance = NULL;
1297 {
1298 auto it = my_data->instanceMap.find(instance);
1299 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
1300 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001301 if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices && (*pPhysicalDeviceCount > 0)) {
Ian Elliott32311832016-02-04 08:17:18 -07001302 // Record the VkPhysicalDevices returned by the ICD:
1303 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001304 my_data->physicalDeviceMap[pPhysicalDevices[i]].physicalDevice = pPhysicalDevices[i];
Ian Elliott32311832016-02-04 08:17:18 -07001305 my_data->physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance;
1306 my_data->physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL;
1307 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotQueueFamilyPropertyCount = false;
1308 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotSurfaceCapabilities = false;
1309 my_data->physicalDeviceMap[pPhysicalDevices[i]].surfaceFormatCount = 0;
1310 my_data->physicalDeviceMap[pPhysicalDevices[i]].pSurfaceFormats = NULL;
1311 my_data->physicalDeviceMap[pPhysicalDevices[i]].presentModeCount = 0;
1312 my_data->physicalDeviceMap[pPhysicalDevices[i]].pPresentModes = NULL;
1313 // Point to the associated SwpInstance:
1314 if (pInstance) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001315 pInstance->physicalDevices[pPhysicalDevices[i]] = &my_data->physicalDeviceMap[pPhysicalDevices[i]];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001316 }
1317 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001318 }
Ian Elliotta3c69bc2016-02-04 15:34:59 -07001319 return result;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001320}
1321
Chia-I Wufccbfe42016-04-28 14:01:30 +08001322VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice physicalDevice,
1323 const VkDeviceCreateInfo *pCreateInfo,
1324 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Chia-I Wua6737532016-04-28 16:04:15 +08001325 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001326 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
1327
1328 assert(chain_info->u.pLayerInfo);
1329 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
1330 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Chia-I Wua6737532016-04-28 16:04:15 +08001331 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001332 if (fpCreateDevice == NULL) {
1333 return VK_ERROR_INITIALIZATION_FAILED;
1334 }
1335
1336 // Advance the link info for the next element on the chain
1337 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
1338
1339 VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1340 if (result != VK_SUCCESS) {
1341 return result;
1342 }
1343
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001344 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001345 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
1346
1347 // Setup device dispatch table
1348 my_device_data->device_dispatch_table = new VkLayerDispatchTable;
1349 layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
1350
1351 my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
1352 createDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice);
1353
1354 return result;
1355}
1356
Chia-I Wufccbfe42016-04-28 14:01:30 +08001357VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001358 dispatch_key key = get_dispatch_key(device);
1359 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001360
1361 // Call down the call chain:
1362 my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
1363
1364 // Do some internal cleanup:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001365 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001366 SwpDevice *pDevice = NULL;
1367 {
1368 auto it = my_data->deviceMap.find(device);
1369 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1370 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001371 if (pDevice) {
1372 // Delete the SwpDevice associated with this device:
1373 if (pDevice->pPhysicalDevice) {
1374 pDevice->pPhysicalDevice->pDevice = NULL;
1375 }
1376 if (!pDevice->swapchains.empty()) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001377 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001378 "%s() called before all of its associated "
1379 "VkSwapchainKHRs were destroyed.",
1380 __FUNCTION__);
1381 // Empty and then delete all SwpSwapchain's
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001382 for (auto it = pDevice->swapchains.begin(); it != pDevice->swapchains.end(); it++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001383 // Delete all SwpImage's
1384 it->second->images.clear();
1385 // In case the swapchain's surface hasn't been destroyed yet
1386 // (which is likely) delete its association with this swapchain
1387 // (i.e. so we can't point to this swpchain from that surface,
1388 // later on):
1389 if (it->second->pSurface) {
1390 it->second->pSurface->swapchains.clear();
1391 }
1392 }
1393 pDevice->swapchains.clear();
1394 }
1395 my_data->deviceMap.erase(device);
1396 }
1397 delete my_data->device_dispatch_table;
1398 layer_data_map.erase(key);
1399}
1400
Chia-I Wufccbfe42016-04-28 14:01:30 +08001401VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
1402 uint32_t queueFamilyIndex, VkSurfaceKHR surface,
1403 VkBool32 *pSupported) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001404 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001405 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001406 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001407 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001408 SwpPhysicalDevice *pPhysicalDevice = NULL;
1409 {
1410 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1411 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1412 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001413
1414 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001415 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1416 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001417 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001418 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1419 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001420 }
1421 if (!pPhysicalDevice->gotQueueFamilyPropertyCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001422 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, "VkPhysicalDevice",
1423 SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES, "%s() called before calling the "
1424 "vkGetPhysicalDeviceQueueFamilyProperties "
1425 "function.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001426 __FUNCTION__);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001427 } else if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
1428 skipCall |=
1429 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
1430 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001431 }
1432 if (!pSupported) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001433 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSupported");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001434 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001435 lock.unlock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001436
Dustin Graves080069b2016-04-05 13:48:15 -06001437 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001438 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001439 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface,
1440 pSupported);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001441 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001442
Ian Elliott32311832016-02-04 08:17:18 -07001443 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001444 {
1445 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1446 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1447 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001448 if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
1449 // Record the result of this query:
1450 SwpInstance *pInstance = pPhysicalDevice->pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001451 SwpSurface *pSurface = (pInstance) ? pInstance->surfaces[surface] : NULL;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001452 if (pSurface) {
1453 pPhysicalDevice->supportedSurfaces[surface] = pSurface;
1454 if (!pSurface->numQueueFamilyIndexSupport) {
1455 if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001456 pSurface->pQueueFamilyIndexSupport =
1457 (VkBool32 *)malloc(pPhysicalDevice->numOfQueueFamilies * sizeof(VkBool32));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001458 if (pSurface->pQueueFamilyIndexSupport != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001459 pSurface->numQueueFamilyIndexSupport = pPhysicalDevice->numOfQueueFamilies;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001460 }
1461 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001462 }
1463 if (pSurface->numQueueFamilyIndexSupport) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001464 pSurface->pQueueFamilyIndexSupport[queueFamilyIndex] = *pSupported;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001465 }
1466 }
1467 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001468 lock.unlock();
1469
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001470 return result;
1471 }
1472 return VK_ERROR_VALIDATION_FAILED_EXT;
1473}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001474
Chia-I Wufccbfe42016-04-28 14:01:30 +08001475VKAPI_ATTR VkResult VKAPI_CALL
1476GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
1477 VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001478 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001479 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001480 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001481 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001482 SwpPhysicalDevice *pPhysicalDevice = NULL;
1483 {
1484 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1485 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1486 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001487
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001488 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001489 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1490 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001491 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001492 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1493 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001494 }
1495 if (!pSurfaceCapabilities) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001496 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceCapabilities");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001497 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001498 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001499
Dustin Graves080069b2016-04-05 13:48:15 -06001500 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001501 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001502 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface,
1503 pSurfaceCapabilities);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001504 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001505
Ian Elliott32311832016-02-04 08:17:18 -07001506 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001507 {
1508 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1509 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1510 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001511 if ((result == VK_SUCCESS) && pPhysicalDevice) {
1512 // Record the result of this query:
1513 pPhysicalDevice->gotSurfaceCapabilities = true;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001514 // FIXME: NEED TO COPY THIS DATA, BECAUSE pSurfaceCapabilities POINTS TO APP-ALLOCATED DATA
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001515 pPhysicalDevice->surfaceCapabilities = *pSurfaceCapabilities;
1516 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001517 lock.unlock();
1518
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001519 return result;
1520 }
1521 return VK_ERROR_VALIDATION_FAILED_EXT;
1522}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001523
Chia-I Wufccbfe42016-04-28 14:01:30 +08001524VKAPI_ATTR VkResult VKAPI_CALL
1525GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount,
1526 VkSurfaceFormatKHR *pSurfaceFormats) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001527 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001528 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001529 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001530 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001531 SwpPhysicalDevice *pPhysicalDevice = NULL;
1532 {
1533 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1534 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1535 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001536
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001537 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001538 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1539 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001540 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001541 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1542 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001543 }
1544 if (!pSurfaceFormatCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001545 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceFormatCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001546 } else if (pPhysicalDevice && pSurfaceFormats) {
1547 // Compare the preliminary value of *pSurfaceFormatCount with the
1548 // value this time:
1549 if (pPhysicalDevice->surfaceFormatCount == 0) {
1550 // Since we haven't recorded a preliminary value of
1551 // *pSurfaceFormatCount, that likely means that the application
1552 // didn't previously call this function with a NULL value of
1553 // pSurfaceFormats:
1554 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
1555 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1556 physicalDevice, "pSurfaceFormatCount", "pSurfaceFormats");
1557 } else if (*pSurfaceFormatCount > pPhysicalDevice->surfaceFormatCount) {
1558 skipCall |= LOG_ERROR_INVALID_COUNT(
1559 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1560 physicalDevice, "pSurfaceFormatCount", "pSurfaceFormats",
1561 *pSurfaceFormatCount, pPhysicalDevice->surfaceFormatCount);
1562 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001563 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001564 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001565
Dustin Graves080069b2016-04-05 13:48:15 -06001566 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001567 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001568 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount,
1569 pSurfaceFormats);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001570 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001571
Ian Elliott32311832016-02-04 08:17:18 -07001572 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001573 {
1574 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1575 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1576 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001577 if ((result == VK_SUCCESS) && pPhysicalDevice && !pSurfaceFormats && pSurfaceFormatCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001578 // Record the result of this preliminary query:
1579 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001580 } else if ((result == VK_SUCCESS) && pPhysicalDevice &&
1581 pSurfaceFormats && pSurfaceFormatCount &&
1582 (*pSurfaceFormatCount > 0)) {
1583 // Record the result of this query:
1584 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
1585 pPhysicalDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)malloc(*pSurfaceFormatCount * sizeof(VkSurfaceFormatKHR));
1586 if (pPhysicalDevice->pSurfaceFormats) {
1587 for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) {
1588 pPhysicalDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001589 }
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001590 } else {
1591 pPhysicalDevice->surfaceFormatCount = 0;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001592 }
1593 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001594 lock.unlock();
1595
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001596 return result;
1597 }
1598 return VK_ERROR_VALIDATION_FAILED_EXT;
1599}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001600
Chia-I Wufccbfe42016-04-28 14:01:30 +08001601VKAPI_ATTR VkResult VKAPI_CALL
1602GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pPresentModeCount,
1603 VkPresentModeKHR *pPresentModes) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001604 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001605 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001606 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001607 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001608 SwpPhysicalDevice *pPhysicalDevice = NULL;
1609 {
1610 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1611 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1612 }
Ian Elliott07adb112016-01-05 12:51:03 -07001613
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001614 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001615 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1616 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001617 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001618 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1619 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001620 }
1621 if (!pPresentModeCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001622 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pPresentModeCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001623 } else if (pPhysicalDevice && pPresentModes) {
1624 // Compare the preliminary value of *pPresentModeCount with the
1625 // value this time:
1626 if (pPhysicalDevice->presentModeCount == 0) {
1627 // Since we haven't recorded a preliminary value of
1628 // *pPresentModeCount, that likely means that the application
1629 // didn't previously call this function with a NULL value of
1630 // pPresentModes:
1631 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
1632 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1633 physicalDevice, "pPresentModeCount", "pPresentModes");
1634 } else if (*pPresentModeCount > pPhysicalDevice->presentModeCount) {
1635 skipCall |= LOG_ERROR_INVALID_COUNT(
1636 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1637 physicalDevice, "pPresentModeCount", "pPresentModes",
1638 *pPresentModeCount, pPhysicalDevice->presentModeCount);
1639 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001640 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001641 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001642
Dustin Graves080069b2016-04-05 13:48:15 -06001643 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001644 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001645 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface,
1646 pPresentModeCount, pPresentModes);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001647 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001648
Ian Elliott32311832016-02-04 08:17:18 -07001649 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001650 {
1651 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1652 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1653 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001654 if ((result == VK_SUCCESS) && pPhysicalDevice && !pPresentModes && pPresentModeCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001655 // Record the result of this preliminary query:
1656 pPhysicalDevice->presentModeCount = *pPresentModeCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001657 } else if ((result == VK_SUCCESS) && pPhysicalDevice &&
1658 pPresentModes && pPresentModeCount &&
1659 (*pPresentModeCount > 0)) {
1660 // Record the result of this query:
1661 pPhysicalDevice->presentModeCount = *pPresentModeCount;
1662 pPhysicalDevice->pPresentModes = (VkPresentModeKHR *)malloc(*pPresentModeCount * sizeof(VkPresentModeKHR));
1663 if (pPhysicalDevice->pPresentModes) {
1664 for (uint32_t i = 0; i < *pPresentModeCount; i++) {
1665 pPhysicalDevice->pPresentModes[i] = pPresentModes[i];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001666 }
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001667 } else {
1668 pPhysicalDevice->presentModeCount = 0;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001669 }
1670 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001671 lock.unlock();
1672
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001673 return result;
1674 }
1675 return VK_ERROR_VALIDATION_FAILED_EXT;
1676}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001677
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001678// This function does the up-front validation work for vkCreateSwapchainKHR(),
Dustin Graves080069b2016-04-05 13:48:15 -06001679// and returns true if a logging callback indicates that the call down the
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001680// chain should be skipped:
Dustin Graves080069b2016-04-05 13:48:15 -06001681static bool validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, VkSwapchainKHR *pSwapchain) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001682 // TODO: Validate cases of re-creating a swapchain (the current code
1683 // assumes a new swapchain is being created).
Dustin Graves080069b2016-04-05 13:48:15 -06001684 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001685 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1686 char fn[] = "vkCreateSwapchainKHR";
Ian Elliott77f46ca2016-05-05 14:10:49 -06001687 SwpDevice *pDevice = NULL;
1688 {
1689 auto it = my_data->deviceMap.find(device);
1690 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1691 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001692
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001693 // Validate that the swapchain extension was enabled:
1694 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001695 return LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1696 "%s() called even though the %s extension was not enabled for this VkDevice.", fn,
1697 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001698 }
1699 if (!pCreateInfo) {
Ian Elliott432a3172016-05-09 12:33:47 -06001700 return LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001701 } else {
1702 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001703 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001704 "VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR");
1705 }
1706 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001707 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001708 }
1709 }
1710 if (!pSwapchain) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001711 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchain");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001712 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001713
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001714 // Keep around a useful pointer to pPhysicalDevice:
1715 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001716
Mark Lobodzinskid40b2db2016-02-25 13:56:57 -07001717 // Validate pCreateInfo values with result of
1718 // vkGetPhysicalDeviceQueueFamilyProperties
1719 if (pPhysicalDevice && pPhysicalDevice->gotQueueFamilyPropertyCount) {
Michael Mc Donnell75ecdb72016-04-03 14:47:51 -07001720 for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001721 if (pCreateInfo->pQueueFamilyIndices[i] >= pPhysicalDevice->numOfQueueFamilies) {
1722 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
1723 "VkPhysicalDevice", pCreateInfo->pQueueFamilyIndices[i],
1724 pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinskid40b2db2016-02-25 13:56:57 -07001725 }
1726 }
1727 }
1728
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001729 // Validate pCreateInfo values with the results of
1730 // vkGetPhysicalDeviceSurfaceCapabilitiesKHR():
1731 if (!pPhysicalDevice || !pPhysicalDevice->gotSurfaceCapabilities) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001732 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001733 "%s() called before calling "
1734 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1735 fn);
1736 } else if (pCreateInfo) {
1737 // Validate pCreateInfo->surface to make sure that
1738 // vkGetPhysicalDeviceSurfaceSupportKHR() reported this as a supported
1739 // surface:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001740 SwpSurface *pSurface = ((pPhysicalDevice) ? pPhysicalDevice->supportedSurfaces[pCreateInfo->surface] : NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001741 if (!pSurface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001742 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001743 "%s() called with pCreateInfo->surface that "
1744 "was not returned by "
1745 "vkGetPhysicalDeviceSurfaceSupportKHR() "
1746 "for the device.",
1747 fn);
1748 }
Ian Elliott4f147fc2016-01-20 08:52:08 -07001749
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001750 // Validate pCreateInfo->minImageCount against
1751 // VkSurfaceCapabilitiesKHR::{min|max}ImageCount:
1752 VkSurfaceCapabilitiesKHR *pCapabilities = &pPhysicalDevice->surfaceCapabilities;
1753 if ((pCreateInfo->minImageCount < pCapabilities->minImageCount) ||
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001754 ((pCapabilities->maxImageCount > 0) && (pCreateInfo->minImageCount > pCapabilities->maxImageCount))) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001755 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001756 SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT, "%s() called with pCreateInfo->minImageCount "
1757 "= %d, which is outside the bounds returned "
1758 "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. "
1759 "minImageCount = %d, maxImageCount = %d).",
1760 fn, pCreateInfo->minImageCount, pCapabilities->minImageCount, pCapabilities->maxImageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001761 }
1762 // Validate pCreateInfo->imageExtent against
1763 // VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
1764 if ((pCapabilities->currentExtent.width == -1) &&
1765 ((pCreateInfo->imageExtent.width < pCapabilities->minImageExtent.width) ||
1766 (pCreateInfo->imageExtent.width > pCapabilities->maxImageExtent.width) ||
1767 (pCreateInfo->imageExtent.height < pCapabilities->minImageExtent.height) ||
1768 (pCreateInfo->imageExtent.height > pCapabilities->maxImageExtent.height))) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001769 skipCall |= LOG_ERROR(
1770 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS,
1771 "%s() called with pCreateInfo->imageExtent = "
1772 "(%d,%d), which is outside the bounds "
1773 "returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): "
1774 "currentExtent = (%d,%d), minImageExtent = "
1775 "(%d,%d), maxImageExtent = (%d,%d).",
1776 fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, pCapabilities->currentExtent.width,
1777 pCapabilities->currentExtent.height, pCapabilities->minImageExtent.width, pCapabilities->minImageExtent.height,
1778 pCapabilities->maxImageExtent.width, pCapabilities->maxImageExtent.height);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001779 }
1780 if ((pCapabilities->currentExtent.width != -1) &&
1781 ((pCreateInfo->imageExtent.width != pCapabilities->currentExtent.width) ||
1782 (pCreateInfo->imageExtent.height != pCapabilities->currentExtent.height))) {
1783 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001784 SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN, "%s() called with pCreateInfo->imageExtent = "
1785 "(%d,%d), which is not equal to the "
1786 "currentExtent = (%d,%d) returned by "
1787 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1788 fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height,
1789 pCapabilities->currentExtent.width, pCapabilities->currentExtent.height);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001790 }
1791 // Validate pCreateInfo->preTransform has one bit set (1st two
1792 // lines of if-statement), which bit is also set in
1793 // VkSurfaceCapabilitiesKHR::supportedTransforms (3rd line of if-statement):
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001794 if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) ||
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001795 !(pCreateInfo->preTransform & pCapabilities->supportedTransforms)) {
1796 // This is an error situation; one for which we'd like to give
1797 // the developer a helpful, multi-line error message. Build it
1798 // up a little at a time, and then log it:
1799 std::string errorString = "";
1800 char str[1024];
1801 // Here's the first part of the message:
1802 sprintf(str, "%s() called with a non-supported "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001803 "pCreateInfo->preTransform (i.e. %s). "
1804 "Supported values are:\n",
1805 fn, surfaceTransformStr(pCreateInfo->preTransform));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001806 errorString += str;
1807 for (int i = 0; i < 32; i++) {
1808 // Build up the rest of the message:
1809 if ((1 << i) & pCapabilities->supportedTransforms) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001810 const char *newStr = surfaceTransformStr((VkSurfaceTransformFlagBitsKHR)(1 << i));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001811 sprintf(str, " %s\n", newStr);
1812 errorString += str;
1813 }
1814 }
1815 // Log the message that we've built up:
Mark Lobodzinskia4cbbcd2016-05-24 15:44:50 -06001816 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1817 reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM, LAYER_NAME,
1818 "%s", errorString.c_str());
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001819 }
1820 // Validate pCreateInfo->compositeAlpha has one bit set (1st two
1821 // lines of if-statement), which bit is also set in
1822 // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha (3rd line of if-statement):
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001823 if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) ||
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001824 !((pCreateInfo->compositeAlpha) & pCapabilities->supportedCompositeAlpha)) {
1825 // This is an error situation; one for which we'd like to give
1826 // the developer a helpful, multi-line error message. Build it
1827 // up a little at a time, and then log it:
1828 std::string errorString = "";
1829 char str[1024];
1830 // Here's the first part of the message:
1831 sprintf(str, "%s() called with a non-supported "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001832 "pCreateInfo->compositeAlpha (i.e. %s). "
1833 "Supported values are:\n",
1834 fn, surfaceCompositeAlphaStr(pCreateInfo->compositeAlpha));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001835 errorString += str;
1836 for (int i = 0; i < 32; i++) {
1837 // Build up the rest of the message:
1838 if ((1 << i) & pCapabilities->supportedCompositeAlpha) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001839 const char *newStr = surfaceCompositeAlphaStr((VkCompositeAlphaFlagBitsKHR)(1 << i));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001840 sprintf(str, " %s\n", newStr);
1841 errorString += str;
1842 }
1843 }
1844 // Log the message that we've built up:
Mark Lobodzinskia4cbbcd2016-05-24 15:44:50 -06001845 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1846 reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA,
1847 LAYER_NAME, "%s", errorString.c_str());
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001848 }
David McFarlande22cfb02016-05-20 18:26:28 -03001849 // Validate pCreateInfo->imageArrayLayers against
1850 // VkSurfaceCapabilitiesKHR::maxImageArrayLayers:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001851 if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > pCapabilities->maxImageArrayLayers)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001852 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
David McFarlande22cfb02016-05-20 18:26:28 -03001853 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_LAYERS, "%s() called with a non-supported "
1854 "pCreateInfo->imageArrayLayers (i.e. %d). "
1855 "Minimum value is 1, maximum value is %d.",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001856 fn, pCreateInfo->imageArrayLayers, pCapabilities->maxImageArrayLayers);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001857 }
1858 // Validate pCreateInfo->imageUsage against
1859 // VkSurfaceCapabilitiesKHR::supportedUsageFlags:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001860 if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & pCapabilities->supportedUsageFlags)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001861 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001862 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS, "%s() called with a non-supported "
1863 "pCreateInfo->imageUsage (i.e. 0x%08x)."
1864 " Supported flag bits are 0x%08x.",
1865 fn, pCreateInfo->imageUsage, pCapabilities->supportedUsageFlags);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001866 }
1867 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001868
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001869 // Validate pCreateInfo values with the results of
1870 // vkGetPhysicalDeviceSurfaceFormatsKHR():
1871 if (!pPhysicalDevice || !pPhysicalDevice->surfaceFormatCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001872 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001873 "%s() called before calling "
1874 "vkGetPhysicalDeviceSurfaceFormatsKHR().",
1875 fn);
1876 } else if (pCreateInfo) {
1877 // Validate pCreateInfo->imageFormat against
1878 // VkSurfaceFormatKHR::format:
1879 bool foundFormat = false;
1880 bool foundColorSpace = false;
1881 bool foundMatch = false;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001882 for (uint32_t i = 0; i < pPhysicalDevice->surfaceFormatCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001883 if (pCreateInfo->imageFormat == pPhysicalDevice->pSurfaceFormats[i].format) {
1884 // Validate pCreateInfo->imageColorSpace against
1885 // VkSurfaceFormatKHR::colorSpace:
1886 foundFormat = true;
1887 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1888 foundMatch = true;
1889 break;
1890 }
1891 } else {
1892 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1893 foundColorSpace = true;
1894 }
1895 }
1896 }
1897 if (!foundMatch) {
1898 if (!foundFormat) {
1899 if (!foundColorSpace) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001900 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1901 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP, "%s() called with neither a "
1902 "supported pCreateInfo->imageFormat "
1903 "(i.e. %d) nor a supported "
1904 "pCreateInfo->imageColorSpace "
1905 "(i.e. %d).",
1906 fn, pCreateInfo->imageFormat, pCreateInfo->imageColorSpace);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001907 } else {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001908 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1909 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT, "%s() called with a non-supported "
1910 "pCreateInfo->imageFormat (i.e. %d).",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001911 fn, pCreateInfo->imageFormat);
1912 }
1913 } else if (!foundColorSpace) {
1914 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001915 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE, "%s() called with a non-supported "
1916 "pCreateInfo->imageColorSpace (i.e. %d).",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001917 fn, pCreateInfo->imageColorSpace);
1918 }
1919 }
1920 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001921
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001922 // Validate pCreateInfo values with the results of
1923 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1924 if (!pPhysicalDevice || !pPhysicalDevice->presentModeCount) {
szdarkhackfb287d32016-03-12 18:41:19 +02001925 if (!pCreateInfo || (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR)) {
1926 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
1927 "%s() called before calling "
1928 "vkGetPhysicalDeviceSurfacePresentModesKHR().",
1929 fn);
1930 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001931 } else if (pCreateInfo) {
1932 // Validate pCreateInfo->presentMode against
1933 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1934 bool foundMatch = false;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001935 for (uint32_t i = 0; i < pPhysicalDevice->presentModeCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001936 if (pPhysicalDevice->pPresentModes[i] == pCreateInfo->presentMode) {
1937 foundMatch = true;
1938 break;
1939 }
1940 }
1941 if (!foundMatch) {
1942 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001943 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE, "%s() called with a non-supported "
1944 "pCreateInfo->presentMode (i.e. %s).",
1945 fn, presentModeStr(pCreateInfo->presentMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001946 }
1947 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001948
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001949 // Validate pCreateInfo->imageSharingMode and related values:
1950 if (pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001951 if ((pCreateInfo->queueFamilyIndexCount <= 1) || !pCreateInfo->pQueueFamilyIndices) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001952 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001953 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_VALUES, "%s() called with a supported "
baldurk209ccda2016-05-05 16:31:05 +02001954 "pCreateInfo->sharingMode of (i.e. %s), "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001955 "but with a bad value(s) for "
1956 "pCreateInfo->queueFamilyIndexCount or "
1957 "pCreateInfo->pQueueFamilyIndices).",
1958 fn, sharingModeStr(pCreateInfo->imageSharingMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001959 }
1960 } else if (pCreateInfo->imageSharingMode != VK_SHARING_MODE_EXCLUSIVE) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001961 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 -07001962 "%s() called with a non-supported "
1963 "pCreateInfo->imageSharingMode (i.e. %s).",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001964 fn, sharingModeStr(pCreateInfo->imageSharingMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001965 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001966
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001967 // Validate pCreateInfo->clipped:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001968 if (pCreateInfo && (pCreateInfo->clipped != VK_FALSE) && (pCreateInfo->clipped != VK_TRUE)) {
1969 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_BAD_BOOL,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001970 "%s() called with a VkBool32 value that is "
1971 "neither VK_TRUE nor VK_FALSE, but has the "
1972 "numeric value of %d.",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001973 fn, pCreateInfo->clipped);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001974 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001975
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001976 // Validate pCreateInfo->oldSwapchain:
1977 if (pCreateInfo && pCreateInfo->oldSwapchain) {
Ian Elliott77f46ca2016-05-05 14:10:49 -06001978 SwpSwapchain *pOldSwapchain = NULL;
1979 {
1980 auto it = my_data->swapchainMap.find(pCreateInfo->oldSwapchain);
1981 pOldSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1982 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001983 if (pOldSwapchain) {
1984 if (device != pOldSwapchain->pDevice->device) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001985 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1986 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE, "%s() called with a different VkDevice "
1987 "than the VkSwapchainKHR was created with.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001988 __FUNCTION__);
1989 }
1990 if (pCreateInfo->surface != pOldSwapchain->pSurface->surface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001991 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1992 SWAPCHAIN_CREATE_SWAP_DIFF_SURFACE, "%s() called with pCreateInfo->oldSwapchain "
1993 "that has a different VkSurfaceKHR than "
1994 "pCreateInfo->surface.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001995 fn);
1996 }
1997 } else {
1998 // TBD: Leave this in (not sure object_track will check this)?
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001999 skipCall |=
2000 LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pCreateInfo->oldSwapchain, "VkSwapchainKHR");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002001 }
2002 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002003
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002004 return skipCall;
2005}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002006
Chia-I Wufccbfe42016-04-28 14:01:30 +08002007VKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
2008 const VkAllocationCallbacks *pAllocator,
2009 VkSwapchainKHR *pSwapchain) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002010 VkResult result = VK_SUCCESS;
2011 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002012 std::unique_lock<std::mutex> lock(global_lock);
Dustin Graves080069b2016-04-05 13:48:15 -06002013 bool skipCall = validateCreateSwapchainKHR(device, pCreateInfo, pSwapchain);
Ian Elliott970a2bd2016-06-21 11:08:43 -06002014 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002015
Dustin Graves080069b2016-04-05 13:48:15 -06002016 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002017 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002018 result = my_data->device_dispatch_table->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002019 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002020
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002021 if (result == VK_SUCCESS) {
2022 // Remember the swapchain's handle, and link it to the device:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002023 SwpDevice *pDevice = NULL;
2024 {
2025 auto it = my_data->deviceMap.find(device);
2026 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2027 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002028
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002029 my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
2030 if (pDevice) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002031 pDevice->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002032 }
2033 my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
2034 my_data->swapchainMap[*pSwapchain].imageCount = 0;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002035 my_data->swapchainMap[*pSwapchain].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002036 // Store a pointer to the surface
2037 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002038 SwpInstance *pInstance = (pPhysicalDevice) ? pPhysicalDevice->pInstance : NULL;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002039 layer_data *my_instance_data =
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002040 ((pInstance) ? get_my_data_ptr(get_dispatch_key(pInstance->instance), layer_data_map) : NULL);
2041 SwpSurface *pSurface = ((my_data && pCreateInfo) ? &my_instance_data->surfaceMap[pCreateInfo->surface] : NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002042 my_data->swapchainMap[*pSwapchain].pSurface = pSurface;
2043 if (pSurface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002044 pSurface->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002045 }
2046 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002047 lock.unlock();
2048
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002049 return result;
2050 }
2051 return VK_ERROR_VALIDATION_FAILED_EXT;
2052}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002053
Chia-I Wufccbfe42016-04-28 14:01:30 +08002054VKAPI_ATTR void VKAPI_CALL
2055DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002056 // TODOs:
2057 //
2058 // - Implement a check for validity language that reads: All uses of
Ian Elliotta5d13a92016-04-07 09:05:45 -06002059 // presentable images acquired from pname:swapchain must: have completed
2060 // execution
Dustin Graves080069b2016-04-05 13:48:15 -06002061 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002062 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002063 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002064 SwpDevice *pDevice = NULL;
2065 {
2066 auto it = my_data->deviceMap.find(device);
2067 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2068 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07002069
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002070 // Validate that the swapchain extension was enabled:
2071 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002072 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2073 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2074 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002075 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002076
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002077 // Regardless of skipCall value, do some internal cleanup:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002078 SwpSwapchain *pSwapchain = NULL;
2079 {
2080 auto it = my_data->swapchainMap.find(swapchain);
2081 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2082 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002083 if (pSwapchain) {
2084 // Delete the SwpSwapchain associated with this swapchain:
2085 if (pSwapchain->pDevice) {
2086 pSwapchain->pDevice->swapchains.erase(swapchain);
2087 if (device != pSwapchain->pDevice->device) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002088 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002089 "%s() called with a different VkDevice than the "
2090 "VkSwapchainKHR was created with.",
2091 __FUNCTION__);
2092 }
2093 }
2094 if (pSwapchain->pSurface) {
2095 pSwapchain->pSurface->swapchains.erase(swapchain);
2096 }
2097 if (pSwapchain->imageCount) {
2098 pSwapchain->images.clear();
2099 }
2100 if ((pAllocator != NULL) != pSwapchain->usedAllocatorToCreate) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002101 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002102 "%s() called with incompatible pAllocator from when "
2103 "the object was created.",
2104 __FUNCTION__);
2105 }
2106 my_data->swapchainMap.erase(swapchain);
2107 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002108 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002109
Dustin Graves080069b2016-04-05 13:48:15 -06002110 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002111 // Call down the call chain:
2112 my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator);
2113 }
2114}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002115
Chia-I Wufccbfe42016-04-28 14:01:30 +08002116VKAPI_ATTR VkResult VKAPI_CALL
2117GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002118 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06002119 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002120 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002121 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002122 SwpDevice *pDevice = NULL;
2123 {
2124 auto it = my_data->deviceMap.find(device);
2125 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2126 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07002127
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002128 // Validate that the swapchain extension was enabled:
2129 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002130 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2131 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2132 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002133 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06002134 SwpSwapchain *pSwapchain = NULL;
2135 {
2136 auto it = my_data->swapchainMap.find(swapchain);
2137 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2138 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002139 if (!pSwapchainImageCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002140 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchainImageCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06002141 } else if (pSwapchain && pSwapchainImages) {
2142 // Compare the preliminary value of *pSwapchainImageCount with the
2143 // value this time:
2144 if (pSwapchain->imageCount == 0) {
2145 // Since we haven't recorded a preliminary value of
2146 // *pSwapchainImageCount, that likely means that the application
2147 // didn't previously call this function with a NULL value of
2148 // pSwapchainImages:
2149 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
2150 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2151 device, "pSwapchainImageCount", "pSwapchainImages");
2152 } else if (*pSwapchainImageCount > pSwapchain->imageCount) {
2153 skipCall |= LOG_ERROR_INVALID_COUNT(
2154 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2155 device, "pSwapchainImageCount", "pSwapchainImages",
2156 *pSwapchainImageCount, pSwapchain->imageCount);
2157 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002158 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002159 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002160
Dustin Graves080069b2016-04-05 13:48:15 -06002161 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002162 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002163 result = my_data->device_dispatch_table->GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002164 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002165
Ian Elliott32311832016-02-04 08:17:18 -07002166 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002167 {
2168 auto it = my_data->swapchainMap.find(swapchain);
2169 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2170 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002171 if ((result == VK_SUCCESS) && pSwapchain && !pSwapchainImages && pSwapchainImageCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002172 // Record the result of this preliminary query:
2173 pSwapchain->imageCount = *pSwapchainImageCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06002174 } else if ((result == VK_SUCCESS) && pSwapchain && pSwapchainImages &&
2175 pSwapchainImageCount && (*pSwapchainImageCount > 0)) {
2176 // Record the images and their state:
2177 pSwapchain->imageCount = *pSwapchainImageCount;
2178 for (uint32_t i = 0; i < *pSwapchainImageCount; i++) {
2179 pSwapchain->images[i].image = pSwapchainImages[i];
2180 pSwapchain->images[i].pSwapchain = pSwapchain;
2181 pSwapchain->images[i].acquiredByApp = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002182 }
2183 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002184 lock.unlock();
2185
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002186 return result;
2187 }
2188 return VK_ERROR_VALIDATION_FAILED_EXT;
2189}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002190
Chia-I Wufccbfe42016-04-28 14:01:30 +08002191VKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
2192 VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002193 // TODOs:
2194 //
2195 // - Address the timeout. Possibilities include looking at the state of the
2196 // swapchain's images, depending on the timeout value.
2197 // - Implement a check for validity language that reads: If pname:semaphore is
2198 // not sname:VK_NULL_HANDLE it must: be unsignalled
2199 // - Implement a check for validity language that reads: If pname:fence is not
2200 // sname:VK_NULL_HANDLE it must: be unsignalled and mustnot: be associated
2201 // with any other queue command that has not yet completed execution on that
2202 // queue
2203 // - Record/update the state of the swapchain, in case an error occurs
2204 // (e.g. VK_ERROR_OUT_OF_DATE_KHR).
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002205 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06002206 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002207 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002208 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002209 SwpDevice *pDevice = NULL;
2210 {
2211 auto it = my_data->deviceMap.find(device);
2212 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2213 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07002214
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002215 // Validate that the swapchain extension was enabled:
2216 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002217 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2218 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2219 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002220 }
Ian Elliottfa8f0322016-03-23 08:28:54 -06002221 if ((semaphore == VK_NULL_HANDLE) && (fence == VK_NULL_HANDLE)) {
Ian Elliott5da0c962016-03-23 11:13:09 -06002222 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_NO_SYNC_FOR_ACQUIRE,
2223 "%s() called with both the semaphore and fence parameters set to "
Jamie Madillcc4e9322016-05-04 12:20:15 -07002224 "VK_NULL_HANDLE (at least one should be used).", __FUNCTION__);
Ian Elliottfa8f0322016-03-23 08:28:54 -06002225 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06002226 SwpSwapchain *pSwapchain = NULL;
2227 {
2228 auto it = my_data->swapchainMap.find(swapchain);
2229 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2230 }
Ian Elliott5c680282016-04-06 14:29:56 -06002231 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
2232 if (pSwapchain && pPhysicalDevice && pPhysicalDevice->gotSurfaceCapabilities) {
2233 // Look to see if the application has already acquired the maximum
2234 // number of images, and this will push it past the spec-defined
2235 // limits:
2236 uint32_t minImageCount = pPhysicalDevice->surfaceCapabilities.minImageCount;
2237 uint32_t imagesAcquiredByApp = 0;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002238 for (uint32_t i = 0; i < pSwapchain->imageCount; i++) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002239 if (pSwapchain->images[i].acquiredByApp) {
Ian Elliott5c680282016-04-06 14:29:56 -06002240 imagesAcquiredByApp++;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002241 }
2242 }
Ian Elliott5c680282016-04-06 14:29:56 -06002243 if (imagesAcquiredByApp > (pSwapchain->imageCount - minImageCount)) {
2244 skipCall |= LOG_ERROR(
2245 VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
2246 swapchain, "VkSwapchainKHR",
2247 SWAPCHAIN_APP_ACQUIRES_TOO_MANY_IMAGES,
2248 "%s() called when it cannot succeed. The application has "
2249 "acquired %d image(s) that have not yet been presented. The "
2250 "maximum number of images that the application can "
2251 "simultaneously acquire from this swapchain (including this "
2252 "call to %s()) is %d. That value is derived by subtracting "
2253 "VkSurfaceCapabilitiesKHR::minImageCount (%d) from the number "
2254 "of images in the swapchain (%d) and adding 1.\n",
2255 __FUNCTION__, imagesAcquiredByApp, __FUNCTION__,
2256 (pSwapchain->imageCount - minImageCount + 1),
2257 minImageCount, pSwapchain->imageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002258 }
2259 }
2260 if (!pImageIndex) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002261 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pImageIndex");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002262 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002263 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002264
Dustin Graves080069b2016-04-05 13:48:15 -06002265 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002266 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002267 result = my_data->device_dispatch_table->AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002268 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002269
Ian Elliott32311832016-02-04 08:17:18 -07002270 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002271 {
2272 auto it = my_data->swapchainMap.find(swapchain);
2273 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2274 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002275 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) && pSwapchain) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002276 // Change the state of the image (now acquired by the application):
2277 pSwapchain->images[*pImageIndex].acquiredByApp = true;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002278 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002279 lock.unlock();
2280
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002281 return result;
2282 }
2283 return VK_ERROR_VALIDATION_FAILED_EXT;
2284}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002285
Chia-I Wufccbfe42016-04-28 14:01:30 +08002286VKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002287 // TODOs:
2288 //
2289 // - Implement a check for validity language that reads: Any given element of
2290 // sname:VkSemaphore in pname:pWaitSemaphores must: refer to a prior signal
2291 // of that sname:VkSemaphore that won't be consumed by any other wait on that
2292 // semaphore
2293 // - Record/update the state of the swapchain, in case an error occurs
2294 // (e.g. VK_ERROR_OUT_OF_DATE_KHR).
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002295 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06002296 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002297 layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002298
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002299 if (!pPresentInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002300 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002301 } else {
2302 if (pPresentInfo->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002303 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002304 "VK_STRUCTURE_TYPE_PRESENT_INFO_KHR");
2305 }
2306 if (pPresentInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002307 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002308 }
2309 if (!pPresentInfo->swapchainCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002310 skipCall |= LOG_ERROR_ZERO_VALUE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->swapchainCount");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002311 }
2312 if (!pPresentInfo->pSwapchains) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002313 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pSwapchains");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002314 }
2315 if (!pPresentInfo->pImageIndices) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002316 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pImageIndices");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002317 }
2318 // Note: pPresentInfo->pResults is allowed to be NULL
2319 }
Ian Elliott046ed2c2015-12-30 17:07:17 -07002320
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002321 std::unique_lock<std::mutex> lock(global_lock);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002322 for (uint32_t i = 0; pPresentInfo && (i < pPresentInfo->swapchainCount); i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002323 uint32_t index = pPresentInfo->pImageIndices[i];
Ian Elliott77f46ca2016-05-05 14:10:49 -06002324 SwpSwapchain *pSwapchain = NULL;
2325 {
2326 auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
2327 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2328 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002329 if (pSwapchain) {
2330 if (!pSwapchain->pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002331 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, pSwapchain->pDevice, "VkDevice",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002332 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002333 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2334 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002335 }
2336 if (index >= pSwapchain->imageCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002337 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
2338 SWAPCHAIN_INDEX_TOO_LARGE, "%s() called for an index that is too "
2339 "large (i.e. %d). There are only %d "
2340 "images in this VkSwapchainKHR.\n",
2341 __FUNCTION__, index, pSwapchain->imageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002342 } else {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002343 if (!pSwapchain->images[index].acquiredByApp) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002344 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i],
2345 "VkSwapchainKHR", SWAPCHAIN_INDEX_NOT_IN_USE, "%s() returned an index (i.e. %d) "
Ian Elliotta5d13a92016-04-07 09:05:45 -06002346 "for an image that is not acquired by "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002347 "the application.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002348 __FUNCTION__, index);
2349 }
2350 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06002351 SwpQueue *pQueue = NULL;
2352 {
2353 auto it = my_data->queueMap.find(queue);
2354 pQueue = (it == my_data->queueMap.end()) ? NULL : &it->second;
2355 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002356 SwpSurface *pSurface = pSwapchain->pSurface;
2357 if (pQueue && pSurface && pSurface->numQueueFamilyIndexSupport) {
2358 uint32_t queueFamilyIndex = pQueue->queueFamilyIndex;
2359 // Note: the 1st test is to ensure queueFamilyIndex is in range,
2360 // and the 2nd test is the validation check:
2361 if ((pSurface->numQueueFamilyIndexSupport > queueFamilyIndex) &&
2362 (!pSurface->pQueueFamilyIndexSupport[queueFamilyIndex])) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002363 skipCall |=
2364 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
2365 SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, "%s() called with a swapchain whose "
2366 "surface is not supported for "
2367 "presention on this device with the "
2368 "queueFamilyIndex (i.e. %d) of the "
2369 "given queue.",
2370 __FUNCTION__, queueFamilyIndex);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002371 }
2372 }
2373 }
2374 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002375 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002376
Dustin Graves080069b2016-04-05 13:48:15 -06002377 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002378 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002379 result = my_data->device_dispatch_table->QueuePresentKHR(queue, pPresentInfo);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002380 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002381
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002382 if (pPresentInfo && ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR))) {
2383 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002384 int index = pPresentInfo->pImageIndices[i];
Ian Elliott77f46ca2016-05-05 14:10:49 -06002385 SwpSwapchain *pSwapchain = NULL;
2386 {
2387 auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
2388 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2389 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002390 if (pSwapchain) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002391 // Change the state of the image (no longer acquired by the
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002392 // application):
Ian Elliotta5d13a92016-04-07 09:05:45 -06002393 pSwapchain->images[index].acquiredByApp = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002394 }
2395 }
2396 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002397 lock.unlock();
2398
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002399 return result;
2400 }
2401 return VK_ERROR_VALIDATION_FAILED_EXT;
2402}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002403
Chia-I Wufccbfe42016-04-28 14:01:30 +08002404VKAPI_ATTR void VKAPI_CALL
2405GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
Dustin Graves080069b2016-04-05 13:48:15 -06002406 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002407 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliottc4db6952016-01-21 14:29:45 -07002408
Dustin Graves080069b2016-04-05 13:48:15 -06002409 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002410 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002411 my_data->device_dispatch_table->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
Ian Elliottc4db6952016-01-21 14:29:45 -07002412
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002413 // Remember the queue's handle, and link it to the device:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002414 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002415 SwpDevice *pDevice = NULL;
2416 {
2417 auto it = my_data->deviceMap.find(device);
2418 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2419 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002420 my_data->queueMap[&pQueue].queue = *pQueue;
2421 if (pDevice) {
2422 pDevice->queues[*pQueue] = &my_data->queueMap[*pQueue];
2423 }
2424 my_data->queueMap[&pQueue].pDevice = pDevice;
2425 my_data->queueMap[&pQueue].queueFamilyIndex = queueFamilyIndex;
2426 }
2427}
Ian Elliottc4db6952016-01-21 14:29:45 -07002428
Chia-I Wufccbfe42016-04-28 14:01:30 +08002429VKAPI_ATTR VkResult VKAPI_CALL
2430CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2431 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002432 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002433 VkResult result =
2434 my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002435 if (VK_SUCCESS == result) {
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002436 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -06002437 result = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002438 }
2439 return result;
2440}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002441
Chia-I Wufccbfe42016-04-28 14:01:30 +08002442VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance,
2443 VkDebugReportCallbackEXT msgCallback,
2444 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002445 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2446 my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002447 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002448 layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
2449}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002450
Chia-I Wufccbfe42016-04-28 14:01:30 +08002451VKAPI_ATTR void VKAPI_CALL
2452DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
2453 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002454 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002455 my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix,
2456 pMsg);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002457}
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07002458
Chia-I Wub02600c2016-05-20 07:11:22 +08002459VKAPI_ATTR VkResult VKAPI_CALL
2460EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
2461 return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
2462}
2463
2464VKAPI_ATTR VkResult VKAPI_CALL
2465EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
2466 return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
2467}
2468
2469VKAPI_ATTR VkResult VKAPI_CALL
2470EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
2471 if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
2472 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
2473
2474 return VK_ERROR_LAYER_NOT_PRESENT;
2475}
2476
Chia-I Wufccbfe42016-04-28 14:01:30 +08002477VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
2478 const char *pLayerName, uint32_t *pCount,
2479 VkExtensionProperties *pProperties) {
Chia-I Wu2b481252016-04-28 14:21:13 +08002480 if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
Chia-I Wu045209e2016-04-28 11:21:49 +08002481 return util_GetExtensionProperties(0, nullptr, pCount, pProperties);
Chia-I Wu2b481252016-04-28 14:21:13 +08002482
2483 assert(physicalDevice);
2484
2485 dispatch_key key = get_dispatch_key(physicalDevice);
2486 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
2487 return my_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002488}
2489
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002490static PFN_vkVoidFunction
Chia-I Wu22813c72016-04-28 14:38:57 +08002491intercept_core_instance_command(const char *name);
2492
2493static PFN_vkVoidFunction
2494intercept_khr_surface_command(const char *name, VkInstance instance);
2495
2496static PFN_vkVoidFunction
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002497intercept_core_device_command(const char *name);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002498
Chia-I Wu83245952016-05-05 16:13:19 +08002499static PFN_vkVoidFunction
2500intercept_khr_swapchain_command(const char *name, VkDevice dev);
2501
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002502VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
2503 PFN_vkVoidFunction proc = intercept_core_device_command(funcName);
2504 if (proc)
2505 return proc;
2506
2507 assert(device);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002508
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002509 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06002510
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002511 my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Courtney Goeltzenleuchter1e9e6c82016-03-19 10:38:52 -06002512 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
Chia-I Wu83245952016-05-05 16:13:19 +08002513
2514 proc = intercept_khr_swapchain_command(funcName, device);
2515 if (proc)
2516 return proc;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002517
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002518 if (pDisp->GetDeviceProcAddr == NULL)
2519 return NULL;
2520 return pDisp->GetDeviceProcAddr(device, funcName);
2521}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002522
Chia-I Wufccbfe42016-04-28 14:01:30 +08002523VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wu22813c72016-04-28 14:38:57 +08002524 PFN_vkVoidFunction proc = intercept_core_instance_command(funcName);
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002525 if (!proc)
2526 proc = intercept_core_device_command(funcName);
2527 if (!proc)
2528 proc = intercept_khr_swapchain_command(funcName, VK_NULL_HANDLE);
Chia-I Wu22813c72016-04-28 14:38:57 +08002529 if (proc)
2530 return proc;
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07002531
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002532 assert(instance);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002533
2534 layer_data *my_data;
2535 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002536 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Ian Elliott68124ac2015-10-07 16:18:35 -06002537
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002538 proc = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
2539 if (!proc)
2540 proc = intercept_khr_surface_command(funcName, instance);
Chia-I Wu22813c72016-04-28 14:38:57 +08002541 if (proc)
2542 return proc;
Ian Elliott0b4d6242015-09-22 10:51:24 -06002543
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002544 if (pTable->GetInstanceProcAddr == NULL)
2545 return NULL;
2546 return pTable->GetInstanceProcAddr(instance, funcName);
2547}
Chia-I Wu045209e2016-04-28 11:21:49 +08002548
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002549static PFN_vkVoidFunction
Chia-I Wu22813c72016-04-28 14:38:57 +08002550intercept_core_instance_command(const char *name) {
2551 static const struct {
2552 const char *name;
2553 PFN_vkVoidFunction proc;
2554 } core_instance_commands[] = {
2555 { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
2556 { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
2557 { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) },
2558 { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
2559 { "vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices) },
Chia-I Wub02600c2016-05-20 07:11:22 +08002560 { "vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties) },
2561 { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
2562 { "vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties) },
Chia-I Wu22813c72016-04-28 14:38:57 +08002563 { "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
2564 { "vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties) },
2565 };
2566
2567 for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
2568 if (!strcmp(core_instance_commands[i].name, name))
2569 return core_instance_commands[i].proc;
2570 }
2571
2572 return nullptr;
2573}
2574
2575static PFN_vkVoidFunction
2576intercept_khr_surface_command(const char *name, VkInstance instance) {
2577 static const struct {
2578 const char *name;
2579 PFN_vkVoidFunction proc;
2580 } khr_surface_commands[] = {
2581#ifdef VK_USE_PLATFORM_ANDROID_KHR
2582 { "vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateAndroidSurfaceKHR) },
2583#endif // VK_USE_PLATFORM_ANDROID_KHR
2584#ifdef VK_USE_PLATFORM_MIR_KHR
2585 { "vkCreateMirSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateMirSurfaceKHR) },
2586 { "vkGetPhysicalDeviceMirPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceMirPresentationSupportKHR) },
2587#endif // VK_USE_PLATFORM_MIR_KHR
2588#ifdef VK_USE_PLATFORM_WAYLAND_KHR
2589 { "vkCreateWaylandSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWaylandSurfaceKHR) },
2590 { "vkGetPhysicalDeviceWaylandPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWaylandPresentationSupportKHR) },
2591#endif // VK_USE_PLATFORM_WAYLAND_KHR
2592#ifdef VK_USE_PLATFORM_WIN32_KHR
2593 { "vkCreateWin32SurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWin32SurfaceKHR) },
2594 { "vkGetPhysicalDeviceWin32PresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWin32PresentationSupportKHR) },
2595#endif // VK_USE_PLATFORM_WIN32_KHR
2596#ifdef VK_USE_PLATFORM_XCB_KHR
2597 { "vkCreateXcbSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXcbSurfaceKHR) },
2598 { "vkGetPhysicalDeviceXcbPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXcbPresentationSupportKHR) },
2599#endif // VK_USE_PLATFORM_XCB_KHR
2600#ifdef VK_USE_PLATFORM_XLIB_KHR
2601 { "vkCreateXlibSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXlibSurfaceKHR) },
2602 { "vkGetPhysicalDeviceXlibPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXlibPresentationSupportKHR) },
2603#endif // VK_USE_PLATFORM_XLIB_KHR
2604 { "vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySurfaceKHR) },
2605 { "vkGetPhysicalDeviceSurfaceSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceSupportKHR) },
2606 { "vkGetPhysicalDeviceSurfaceCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceCapabilitiesKHR) },
2607 { "vkGetPhysicalDeviceSurfaceFormatsKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceFormatsKHR) },
2608 { "vkGetPhysicalDeviceSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfacePresentModesKHR) },
Petros Bantolas2b40be72016-04-15 11:02:59 +01002609 { "vkGetPhysicalDeviceDisplayPropertiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceDisplayPropertiesKHR) },
2610 { "vkGetPhysicalDeviceDisplayPlanePropertiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceDisplayPlanePropertiesKHR) },
2611 { "vkGetDisplayPlaneSupportedDisplaysKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayPlaneSupportedDisplaysKHR) },
2612 { "vkGetDisplayModePropertiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayModePropertiesKHR) },
2613 { "vkCreateDisplayModeKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDisplayModeKHR) },
2614 { "vkGetDisplayPlaneCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayPlaneCapabilitiesKHR) },
2615 { "vkCreateDisplayPlaneSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDisplayPlaneSurfaceKHR) },
Chia-I Wu22813c72016-04-28 14:38:57 +08002616 };
2617
2618 // do not check if VK_KHR_*_surface is enabled (why?)
2619
2620 for (size_t i = 0; i < ARRAY_SIZE(khr_surface_commands); i++) {
2621 if (!strcmp(khr_surface_commands[i].name, name))
2622 return khr_surface_commands[i].proc;
2623 }
2624
2625 return nullptr;
2626}
2627
2628static PFN_vkVoidFunction
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002629intercept_core_device_command(const char *name) {
2630 static const struct {
2631 const char *name;
2632 PFN_vkVoidFunction proc;
2633 } core_device_commands[] = {
2634 { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
2635 { "vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice) },
2636 { "vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue) },
2637 };
2638
2639 for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) {
2640 if (!strcmp(core_device_commands[i].name, name))
2641 return core_device_commands[i].proc;
2642 }
2643
2644 return nullptr;
2645}
2646
Chia-I Wu83245952016-05-05 16:13:19 +08002647static PFN_vkVoidFunction
2648intercept_khr_swapchain_command(const char *name, VkDevice dev) {
2649 static const struct {
2650 const char *name;
2651 PFN_vkVoidFunction proc;
2652 } khr_swapchain_commands[] = {
2653 { "vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR) },
2654 { "vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR) },
2655 { "vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR) },
2656 { "vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR) },
2657 { "vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR) },
2658 };
2659
2660 // do not check if VK_KHR_swapchain is enabled (why?)
2661
2662 for (size_t i = 0; i < ARRAY_SIZE(khr_swapchain_commands); i++) {
2663 if (!strcmp(khr_swapchain_commands[i].name, name))
2664 return khr_swapchain_commands[i].proc;
2665 }
2666
2667 return nullptr;
2668}
2669
Chia-I Wu516b5082016-04-28 11:27:46 +08002670} // namespace swapchain
2671
2672// vk_layer_logging.h expects these to be defined
2673
Chia-I Wufccbfe42016-04-28 14:01:30 +08002674VKAPI_ATTR VkResult VKAPI_CALL
Chia-I Wu516b5082016-04-28 11:27:46 +08002675vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2676 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002677 return swapchain::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Chia-I Wu516b5082016-04-28 11:27:46 +08002678}
2679
Chia-I Wufccbfe42016-04-28 14:01:30 +08002680VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance,
Chia-I Wu516b5082016-04-28 11:27:46 +08002681 VkDebugReportCallbackEXT msgCallback,
2682 const VkAllocationCallbacks *pAllocator) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002683 swapchain::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Chia-I Wu516b5082016-04-28 11:27:46 +08002684}
2685
Chia-I Wufccbfe42016-04-28 14:01:30 +08002686VKAPI_ATTR void VKAPI_CALL
Chia-I Wu516b5082016-04-28 11:27:46 +08002687vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
2688 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002689 swapchain::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
Chia-I Wu516b5082016-04-28 11:27:46 +08002690}
2691
Chia-I Wub02600c2016-05-20 07:11:22 +08002692// loader-layer interface v0, just wrappers since there is only a layer
Chia-I Wu516b5082016-04-28 11:27:46 +08002693
Chia-I Wu045209e2016-04-28 11:21:49 +08002694VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2695vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002696 return swapchain::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002697}
2698
2699VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2700vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002701 return swapchain::EnumerateInstanceLayerProperties(pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002702}
2703
2704VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2705vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002706 // the layer command handles VK_NULL_HANDLE just fine internally
2707 assert(physicalDevice == VK_NULL_HANDLE);
2708 return swapchain::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
Chia-I Wu516b5082016-04-28 11:27:46 +08002709}
2710
2711VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
2712 const char *pLayerName, uint32_t *pCount,
2713 VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002714 // the layer command handles VK_NULL_HANDLE just fine internally
2715 assert(physicalDevice == VK_NULL_HANDLE);
Chia-I Wu2b481252016-04-28 14:21:13 +08002716 return swapchain::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
Chia-I Wu516b5082016-04-28 11:27:46 +08002717}
2718
2719VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002720 return swapchain::GetDeviceProcAddr(dev, funcName);
Chia-I Wu516b5082016-04-28 11:27:46 +08002721}
2722
2723VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002724 return swapchain::GetInstanceProcAddr(instance, funcName);
Chia-I Wu045209e2016-04-28 11:21:49 +08002725}