blob: e472c9888afd2e69f0368287c5b0dae8ac7e85d4 [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 }
Jon Ashburne699f442016-06-30 09:01:27 -0600957 // TODO add check for the count being consistent
Petros Bantolas2b40be72016-04-15 11:02:59 +0100958 lock.unlock();
959
960 if (!skipCall) {
961 result = my_data->instance_dispatch_table->GetPhysicalDeviceDisplayPropertiesKHR(physicalDevice, pPropertyCount, pProperties);
962 return result;
963 }
964 return VK_ERROR_VALIDATION_FAILED_EXT;
965}
966
Petros Bantolas2b40be72016-04-15 11:02:59 +0100967VKAPI_ATTR VkResult VKAPI_CALL
968GetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkDisplayPlanePropertiesKHR *pProperties) {
969 VkResult result = VK_SUCCESS;
970 bool skipCall = false;
971 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
972 std::unique_lock<std::mutex> lock(global_lock);
973 SwpPhysicalDevice *pPhysicalDevice = NULL;
974 {
975 auto it = my_data->physicalDeviceMap.find(physicalDevice);
976 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
977 }
978
979 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
980 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
981 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
982 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
983 VK_KHR_DISPLAY_EXTENSION_NAME);
984 }
985
986 if (!pPropertyCount) {
987 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pPropertyCount");
988 }
Jon Ashburne699f442016-06-30 09:01:27 -0600989 // TODO add check for the count being consistent
Petros Bantolas2b40be72016-04-15 11:02:59 +0100990 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 }
Jon Ashburne699f442016-06-30 09:01:27 -06001001 // TODO store the properties for later checks
Petros Bantolas2b40be72016-04-15 11:02:59 +01001002 lock.unlock();
1003
1004 return result;
1005 }
1006 return VK_ERROR_VALIDATION_FAILED_EXT;
1007}
1008
1009VKAPI_ATTR VkResult VKAPI_CALL
1010GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays) {
1011 VkResult result = VK_SUCCESS;
1012 bool skipCall = false;
1013 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1014 std::unique_lock<std::mutex> lock(global_lock);
1015 SwpPhysicalDevice *pPhysicalDevice = NULL;
1016 {
1017 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1018 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1019 }
1020
1021 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
1022 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1023 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1024 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1025 VK_KHR_DISPLAY_EXTENSION_NAME);
1026 }
1027
1028 if (!pDisplayCount) {
1029 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pDisplayCount");
1030 }
Jon Ashburne699f442016-06-30 09:01:27 -06001031 // TODO add check for the count being consistent
Petros Bantolas2b40be72016-04-15 11:02:59 +01001032
Jon Ashburn5e026df2016-06-15 08:19:07 -06001033 if (!pPhysicalDevice->gotDisplayPlanePropertyCount)
Petros Bantolas2b40be72016-04-15 11:02:59 +01001034 {
1035 LOG_WARNING(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
1036 SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY,
1037 "Potential problem with calling %s() without first querying vkGetPhysicalDeviceDisplayPlanePropertiesKHR.",
1038 __FUNCTION__);
1039 }
1040
Jon Ashburn5e026df2016-06-15 08:19:07 -06001041 if (pPhysicalDevice->gotDisplayPlanePropertyCount && planeIndex >= pPhysicalDevice->gotDisplayPlanePropertyCount)
Petros Bantolas2b40be72016-04-15 11:02:59 +01001042 {
1043 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
1044 SWAPCHAIN_PLANE_INDEX_TOO_LARGE,
1045 "%s(): %s must be in the range [0, %d] that was returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR. Do you have the plane index hardcoded?",
1046 __FUNCTION__,
1047 "planeIndex",
Jon Ashburn5e026df2016-06-15 08:19:07 -06001048 pPhysicalDevice->displayPlanePropertyCount - 1);
Petros Bantolas2b40be72016-04-15 11:02:59 +01001049 }
1050 lock.unlock();
1051
1052 if (!skipCall) {
1053 result = my_data->instance_dispatch_table->GetDisplayPlaneSupportedDisplaysKHR(physicalDevice, planeIndex, pDisplayCount, pDisplays);
1054
1055 return result;
1056 }
Jon Ashburne699f442016-06-30 09:01:27 -06001057 // TODO validate the returned display objects
Petros Bantolas2b40be72016-04-15 11:02:59 +01001058 return VK_ERROR_VALIDATION_FAILED_EXT;
1059}
1060
1061VKAPI_ATTR VkResult VKAPI_CALL
1062GetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties) {
1063 VkResult result = VK_SUCCESS;
1064 bool skipCall = false;
1065 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1066 std::unique_lock<std::mutex> lock(global_lock);
1067 SwpPhysicalDevice *pPhysicalDevice = NULL;
1068 {
1069 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1070 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1071 }
1072
1073 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
1074 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1075 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1076 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1077 VK_KHR_DISPLAY_EXTENSION_NAME);
1078 }
1079
1080 if (!pPropertyCount) {
1081 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pPropertyCount");
1082 }
Jon Ashburne699f442016-06-30 09:01:27 -06001083 // TODO add check for the count being consistent
Petros Bantolas2b40be72016-04-15 11:02:59 +01001084 lock.unlock();
1085
1086 if (!skipCall) {
1087 result = my_data->instance_dispatch_table->GetDisplayModePropertiesKHR(physicalDevice, display, pPropertyCount, pProperties);
1088 return result;
1089 }
Jon Ashburne699f442016-06-30 09:01:27 -06001090 // TODO store the displayMode for later checking
Petros Bantolas2b40be72016-04-15 11:02:59 +01001091 return VK_ERROR_VALIDATION_FAILED_EXT;
1092}
1093
1094VKAPI_ATTR VkResult VKAPI_CALL
1095CreateDisplayModeKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode) {
1096 VkResult result = VK_SUCCESS;
1097 bool skipCall = false;
1098 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1099 std::unique_lock<std::mutex> lock(global_lock);
1100 SwpPhysicalDevice *pPhysicalDevice = NULL;
1101 {
1102 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1103 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1104 }
1105
1106 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
1107 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1108 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1109 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1110 VK_KHR_DISPLAY_EXTENSION_NAME);
1111 }
1112
1113 if (!pCreateInfo) {
1114 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pCreateInfo");
1115 }
1116 lock.unlock();
1117
Jon Ashburne699f442016-06-30 09:01:27 -06001118 // TODO more validation checks needed
Petros Bantolas2b40be72016-04-15 11:02:59 +01001119 if (!skipCall) {
1120 result = my_data->instance_dispatch_table->CreateDisplayModeKHR(physicalDevice, display, pCreateInfo, pAllocator, pMode);
1121 return result;
1122 }
1123
1124 return VK_ERROR_VALIDATION_FAILED_EXT;
1125}
1126
1127VKAPI_ATTR VkResult VKAPI_CALL
1128GetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR* pCapabilities) {
1129 VkResult result = VK_SUCCESS;
1130 bool skipCall = false;
1131 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1132 std::unique_lock<std::mutex> lock(global_lock);
1133 SwpPhysicalDevice *pPhysicalDevice = NULL;
1134 {
1135 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1136 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1137 }
1138
1139 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->displayExtensionEnabled) {
1140 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
1141 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1142 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1143 VK_KHR_DISPLAY_EXTENSION_NAME);
1144 }
1145
Jon Ashburn5e026df2016-06-15 08:19:07 -06001146 if (!pPhysicalDevice->gotDisplayPlanePropertyCount)
Petros Bantolas2b40be72016-04-15 11:02:59 +01001147 {
1148 LOG_WARNING(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
1149 SWAPCHAIN_GET_SUPPORTED_DISPLAYS_WITHOUT_QUERY,
1150 "Potential problem with calling %s() without first querying vkGetPhysicalDeviceDisplayPlanePropertiesKHR.",
1151 __FUNCTION__);
1152 }
1153
Jon Ashburn5e026df2016-06-15 08:19:07 -06001154 if (pPhysicalDevice->gotDisplayPlanePropertyCount && planeIndex >= pPhysicalDevice->displayPlanePropertyCount)
Petros Bantolas2b40be72016-04-15 11:02:59 +01001155 {
1156 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "planeIndex",
1157 SWAPCHAIN_PLANE_INDEX_TOO_LARGE,
1158 "%s(): %s must be in the range [0, %d] that was returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR. Do you have the plane index hardcoded?",
1159 __FUNCTION__,
1160 "planeIndex",
Jon Ashburn5e026df2016-06-15 08:19:07 -06001161 pPhysicalDevice->displayPlanePropertyCount - 1);
Petros Bantolas2b40be72016-04-15 11:02:59 +01001162 }
1163
1164 if (!pCapabilities) {
1165 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "pCapabilities");
1166 }
1167 lock.unlock();
1168
1169 if (!skipCall) {
1170 result = my_data->instance_dispatch_table->GetDisplayPlaneCapabilitiesKHR(physicalDevice, mode, planeIndex, pCapabilities);
1171 return result;
1172 }
1173
1174 return VK_ERROR_VALIDATION_FAILED_EXT;
1175}
1176
1177VKAPI_ATTR VkResult VKAPI_CALL
1178CreateDisplayPlaneSurfaceKHR(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
1179 VkSurfaceKHR *pSurface) {
1180 VkResult result = VK_SUCCESS;
1181 bool skipCall = false;
1182 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1183 std::unique_lock<std::mutex> lock(global_lock);
1184 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
1185
1186 // Validate that the platform extension was enabled:
1187 if (pInstance && !pInstance->displayExtensionEnabled) {
1188 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1189 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1190 VK_KHR_DISPLAY_EXTENSION_NAME);
1191 }
1192
1193 if (!pCreateInfo) {
1194 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
1195 } else {
1196 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR) {
1197 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
1198 "VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR");
1199 }
1200 if (pCreateInfo->pNext != NULL) {
1201 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
1202 }
1203 }
1204
Jon Ashburne699f442016-06-30 09:01:27 -06001205 // TODO more validation checks
Petros Bantolas2b40be72016-04-15 11:02:59 +01001206 if (!skipCall) {
1207 // Call down the call chain:
1208 lock.unlock();
1209 result = my_data->instance_dispatch_table->CreateDisplayPlaneSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
1210 lock.lock();
1211
1212 // Obtain this pointer again after locking:
1213 pInstance = &(my_data->instanceMap[instance]);
1214 if ((result == VK_SUCCESS) && pInstance && pSurface) {
1215 // Record the VkSurfaceKHR returned by the ICD:
1216 my_data->surfaceMap[*pSurface].surface = *pSurface;
1217 my_data->surfaceMap[*pSurface].pInstance = pInstance;
1218 my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
1219 my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
1220 my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
1221 // Point to the associated SwpInstance:
1222 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
1223 }
1224 lock.unlock();
1225 return result;
1226 }
1227 return VK_ERROR_VALIDATION_FAILED_EXT;
1228}
1229
Chia-I Wufccbfe42016-04-28 14:01:30 +08001230VKAPI_ATTR void VKAPI_CALL
1231DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) {
Dustin Graves080069b2016-04-05 13:48:15 -06001232 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001233 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001234 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001235 SwpSurface *pSurface = NULL;
1236 {
1237 auto it = my_data->surfaceMap.find(surface);
1238 pSurface = (it == my_data->surfaceMap.end()) ? NULL : &it->second;
1239 }
1240 SwpInstance *pInstance = NULL;
1241 {
1242 auto it = my_data->instanceMap.find(instance);
1243 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
1244 }
Ian Elliottf6b8c782016-04-29 13:03:17 -06001245
1246 // Validate that the platform extension was enabled:
1247 if (pInstance && !pInstance->surfaceExtensionEnabled) {
1248 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1249 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1250 VK_KHR_SURFACE_EXTENSION_NAME);
1251 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001252
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001253 // Regardless of skipCall value, do some internal cleanup:
1254 if (pSurface) {
1255 // Delete the SwpSurface associated with this surface:
1256 if (pSurface->pInstance) {
1257 pSurface->pInstance->surfaces.erase(surface);
1258 }
1259 if (!pSurface->swapchains.empty()) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001260 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001261 "%s() called before all of its associated "
1262 "VkSwapchainKHRs were destroyed.",
1263 __FUNCTION__);
1264 // Empty and then delete all SwpSwapchain's
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001265 for (auto it = pSurface->swapchains.begin(); it != pSurface->swapchains.end(); it++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001266 // Delete all SwpImage's
1267 it->second->images.clear();
1268 // In case the swapchain's device hasn't been destroyed yet
1269 // (which isn't likely, but is possible), delete its
1270 // association with this swapchain (i.e. so we can't point to
1271 // this swpchain from that device, later on):
1272 if (it->second->pDevice) {
1273 it->second->pDevice->swapchains.clear();
1274 }
1275 }
1276 pSurface->swapchains.clear();
1277 }
1278 if ((pAllocator != NULL) != pSurface->usedAllocatorToCreate) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001279 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001280 "%s() called with incompatible pAllocator from when "
1281 "the object was created.",
1282 __FUNCTION__);
1283 }
1284 my_data->surfaceMap.erase(surface);
1285 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001286 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001287
Dustin Graves080069b2016-04-05 13:48:15 -06001288 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001289 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001290 my_data->instance_dispatch_table->DestroySurfaceKHR(instance, surface, pAllocator);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001291 }
1292}
1293
Chia-I Wufccbfe42016-04-28 14:01:30 +08001294VKAPI_ATTR VkResult VKAPI_CALL
1295EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001296 VkResult result = VK_SUCCESS;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001297 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001298
1299 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001300 result = my_data->instance_dispatch_table->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
Ian Elliott32311832016-02-04 08:17:18 -07001301
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001302 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001303 SwpInstance *pInstance = NULL;
1304 {
1305 auto it = my_data->instanceMap.find(instance);
1306 pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
1307 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001308 if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices && (*pPhysicalDeviceCount > 0)) {
Ian Elliott32311832016-02-04 08:17:18 -07001309 // Record the VkPhysicalDevices returned by the ICD:
1310 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001311 my_data->physicalDeviceMap[pPhysicalDevices[i]].physicalDevice = pPhysicalDevices[i];
Ian Elliott32311832016-02-04 08:17:18 -07001312 my_data->physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance;
1313 my_data->physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL;
1314 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotQueueFamilyPropertyCount = false;
1315 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotSurfaceCapabilities = false;
1316 my_data->physicalDeviceMap[pPhysicalDevices[i]].surfaceFormatCount = 0;
1317 my_data->physicalDeviceMap[pPhysicalDevices[i]].pSurfaceFormats = NULL;
1318 my_data->physicalDeviceMap[pPhysicalDevices[i]].presentModeCount = 0;
1319 my_data->physicalDeviceMap[pPhysicalDevices[i]].pPresentModes = NULL;
1320 // Point to the associated SwpInstance:
1321 if (pInstance) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001322 pInstance->physicalDevices[pPhysicalDevices[i]] = &my_data->physicalDeviceMap[pPhysicalDevices[i]];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001323 }
1324 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001325 }
Ian Elliotta3c69bc2016-02-04 15:34:59 -07001326 return result;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001327}
1328
Chia-I Wufccbfe42016-04-28 14:01:30 +08001329VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice physicalDevice,
1330 const VkDeviceCreateInfo *pCreateInfo,
1331 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Chia-I Wua6737532016-04-28 16:04:15 +08001332 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001333 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
1334
1335 assert(chain_info->u.pLayerInfo);
1336 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
1337 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Chia-I Wua6737532016-04-28 16:04:15 +08001338 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001339 if (fpCreateDevice == NULL) {
1340 return VK_ERROR_INITIALIZATION_FAILED;
1341 }
1342
1343 // Advance the link info for the next element on the chain
1344 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
1345
1346 VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1347 if (result != VK_SUCCESS) {
1348 return result;
1349 }
1350
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001351 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001352 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
1353
1354 // Setup device dispatch table
1355 my_device_data->device_dispatch_table = new VkLayerDispatchTable;
1356 layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
1357
1358 my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
1359 createDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice);
1360
1361 return result;
1362}
1363
Chia-I Wufccbfe42016-04-28 14:01:30 +08001364VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001365 dispatch_key key = get_dispatch_key(device);
1366 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott32311832016-02-04 08:17:18 -07001367
1368 // Call down the call chain:
1369 my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
1370
1371 // Do some internal cleanup:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001372 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001373 SwpDevice *pDevice = NULL;
1374 {
1375 auto it = my_data->deviceMap.find(device);
1376 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1377 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001378 if (pDevice) {
1379 // Delete the SwpDevice associated with this device:
1380 if (pDevice->pPhysicalDevice) {
1381 pDevice->pPhysicalDevice->pDevice = NULL;
1382 }
1383 if (!pDevice->swapchains.empty()) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001384 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001385 "%s() called before all of its associated "
1386 "VkSwapchainKHRs were destroyed.",
1387 __FUNCTION__);
1388 // Empty and then delete all SwpSwapchain's
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001389 for (auto it = pDevice->swapchains.begin(); it != pDevice->swapchains.end(); it++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001390 // Delete all SwpImage's
1391 it->second->images.clear();
1392 // In case the swapchain's surface hasn't been destroyed yet
1393 // (which is likely) delete its association with this swapchain
1394 // (i.e. so we can't point to this swpchain from that surface,
1395 // later on):
1396 if (it->second->pSurface) {
1397 it->second->pSurface->swapchains.clear();
1398 }
1399 }
1400 pDevice->swapchains.clear();
1401 }
1402 my_data->deviceMap.erase(device);
1403 }
1404 delete my_data->device_dispatch_table;
1405 layer_data_map.erase(key);
1406}
1407
Chia-I Wufccbfe42016-04-28 14:01:30 +08001408VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
1409 uint32_t queueFamilyIndex, VkSurfaceKHR surface,
1410 VkBool32 *pSupported) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001411 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001412 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001413 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001414 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001415 SwpPhysicalDevice *pPhysicalDevice = NULL;
1416 {
1417 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1418 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1419 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001420
1421 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001422 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1423 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001424 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001425 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1426 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001427 }
1428 if (!pPhysicalDevice->gotQueueFamilyPropertyCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001429 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, "VkPhysicalDevice",
1430 SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES, "%s() called before calling the "
1431 "vkGetPhysicalDeviceQueueFamilyProperties "
1432 "function.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001433 __FUNCTION__);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001434 } else if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
1435 skipCall |=
1436 LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
1437 "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001438 }
1439 if (!pSupported) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001440 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSupported");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001441 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001442 lock.unlock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001443
Dustin Graves080069b2016-04-05 13:48:15 -06001444 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001445 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001446 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface,
1447 pSupported);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001448 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001449
Ian Elliott32311832016-02-04 08:17:18 -07001450 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001451 {
1452 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1453 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1454 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001455 if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
1456 // Record the result of this query:
1457 SwpInstance *pInstance = pPhysicalDevice->pInstance;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001458 SwpSurface *pSurface = (pInstance) ? pInstance->surfaces[surface] : NULL;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001459 if (pSurface) {
1460 pPhysicalDevice->supportedSurfaces[surface] = pSurface;
1461 if (!pSurface->numQueueFamilyIndexSupport) {
1462 if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001463 pSurface->pQueueFamilyIndexSupport =
1464 (VkBool32 *)malloc(pPhysicalDevice->numOfQueueFamilies * sizeof(VkBool32));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001465 if (pSurface->pQueueFamilyIndexSupport != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001466 pSurface->numQueueFamilyIndexSupport = pPhysicalDevice->numOfQueueFamilies;
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001467 }
1468 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001469 }
1470 if (pSurface->numQueueFamilyIndexSupport) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001471 pSurface->pQueueFamilyIndexSupport[queueFamilyIndex] = *pSupported;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001472 }
1473 }
1474 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001475 lock.unlock();
1476
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001477 return result;
1478 }
1479 return VK_ERROR_VALIDATION_FAILED_EXT;
1480}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001481
Chia-I Wufccbfe42016-04-28 14:01:30 +08001482VKAPI_ATTR VkResult VKAPI_CALL
1483GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
1484 VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001485 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001486 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001487 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001488 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001489 SwpPhysicalDevice *pPhysicalDevice = NULL;
1490 {
1491 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1492 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1493 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001494
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001495 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001496 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1497 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001498 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001499 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1500 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001501 }
1502 if (!pSurfaceCapabilities) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001503 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceCapabilities");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001504 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001505 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001506
Dustin Graves080069b2016-04-05 13:48:15 -06001507 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001508 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001509 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface,
1510 pSurfaceCapabilities);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001511 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001512
Ian Elliott32311832016-02-04 08:17:18 -07001513 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001514 {
1515 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1516 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1517 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001518 if ((result == VK_SUCCESS) && pPhysicalDevice) {
1519 // Record the result of this query:
1520 pPhysicalDevice->gotSurfaceCapabilities = true;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001521 // FIXME: NEED TO COPY THIS DATA, BECAUSE pSurfaceCapabilities POINTS TO APP-ALLOCATED DATA
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001522 pPhysicalDevice->surfaceCapabilities = *pSurfaceCapabilities;
1523 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001524 lock.unlock();
1525
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001526 return result;
1527 }
1528 return VK_ERROR_VALIDATION_FAILED_EXT;
1529}
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001530
Chia-I Wufccbfe42016-04-28 14:01:30 +08001531VKAPI_ATTR VkResult VKAPI_CALL
1532GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount,
1533 VkSurfaceFormatKHR *pSurfaceFormats) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001534 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001535 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001536 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001537 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001538 SwpPhysicalDevice *pPhysicalDevice = NULL;
1539 {
1540 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1541 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1542 }
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001543
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001544 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001545 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1546 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001547 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001548 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1549 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001550 }
1551 if (!pSurfaceFormatCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001552 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceFormatCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001553 } else if (pPhysicalDevice && pSurfaceFormats) {
1554 // Compare the preliminary value of *pSurfaceFormatCount with the
1555 // value this time:
1556 if (pPhysicalDevice->surfaceFormatCount == 0) {
1557 // Since we haven't recorded a preliminary value of
1558 // *pSurfaceFormatCount, that likely means that the application
1559 // didn't previously call this function with a NULL value of
1560 // pSurfaceFormats:
1561 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
1562 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1563 physicalDevice, "pSurfaceFormatCount", "pSurfaceFormats");
1564 } else if (*pSurfaceFormatCount > pPhysicalDevice->surfaceFormatCount) {
1565 skipCall |= LOG_ERROR_INVALID_COUNT(
1566 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1567 physicalDevice, "pSurfaceFormatCount", "pSurfaceFormats",
1568 *pSurfaceFormatCount, pPhysicalDevice->surfaceFormatCount);
1569 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001570 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001571 lock.unlock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001572
Dustin Graves080069b2016-04-05 13:48:15 -06001573 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001574 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001575 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount,
1576 pSurfaceFormats);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001577 lock.lock();
Mark Lobodzinskib39d9e62016-02-02 17:06:29 -07001578
Ian Elliott32311832016-02-04 08:17:18 -07001579 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001580 {
1581 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1582 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1583 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001584 if ((result == VK_SUCCESS) && pPhysicalDevice && !pSurfaceFormats && pSurfaceFormatCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001585 // Record the result of this preliminary query:
1586 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001587 } else if ((result == VK_SUCCESS) && pPhysicalDevice &&
1588 pSurfaceFormats && pSurfaceFormatCount &&
1589 (*pSurfaceFormatCount > 0)) {
1590 // Record the result of this query:
1591 pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
1592 pPhysicalDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)malloc(*pSurfaceFormatCount * sizeof(VkSurfaceFormatKHR));
1593 if (pPhysicalDevice->pSurfaceFormats) {
1594 for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) {
1595 pPhysicalDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001596 }
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001597 } else {
1598 pPhysicalDevice->surfaceFormatCount = 0;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001599 }
1600 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001601 lock.unlock();
1602
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001603 return result;
1604 }
1605 return VK_ERROR_VALIDATION_FAILED_EXT;
1606}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001607
Chia-I Wufccbfe42016-04-28 14:01:30 +08001608VKAPI_ATTR VkResult VKAPI_CALL
1609GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pPresentModeCount,
1610 VkPresentModeKHR *pPresentModes) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001611 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06001612 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001613 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001614 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06001615 SwpPhysicalDevice *pPhysicalDevice = NULL;
1616 {
1617 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1618 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1619 }
Ian Elliott07adb112016-01-05 12:51:03 -07001620
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001621 // Validate that the surface extension was enabled:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001622 if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
1623 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001624 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001625 "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
1626 VK_KHR_SURFACE_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001627 }
1628 if (!pPresentModeCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001629 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pPresentModeCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001630 } else if (pPhysicalDevice && pPresentModes) {
1631 // Compare the preliminary value of *pPresentModeCount with the
1632 // value this time:
1633 if (pPhysicalDevice->presentModeCount == 0) {
1634 // Since we haven't recorded a preliminary value of
1635 // *pPresentModeCount, that likely means that the application
1636 // didn't previously call this function with a NULL value of
1637 // pPresentModes:
1638 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
1639 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1640 physicalDevice, "pPresentModeCount", "pPresentModes");
1641 } else if (*pPresentModeCount > pPhysicalDevice->presentModeCount) {
1642 skipCall |= LOG_ERROR_INVALID_COUNT(
1643 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
1644 physicalDevice, "pPresentModeCount", "pPresentModes",
1645 *pPresentModeCount, pPhysicalDevice->presentModeCount);
1646 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001647 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001648 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06001649
Dustin Graves080069b2016-04-05 13:48:15 -06001650 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001651 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001652 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface,
1653 pPresentModeCount, pPresentModes);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06001654 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001655
Ian Elliott32311832016-02-04 08:17:18 -07001656 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06001657 {
1658 auto it = my_data->physicalDeviceMap.find(physicalDevice);
1659 pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
1660 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001661 if ((result == VK_SUCCESS) && pPhysicalDevice && !pPresentModes && pPresentModeCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001662 // Record the result of this preliminary query:
1663 pPhysicalDevice->presentModeCount = *pPresentModeCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001664 } else if ((result == VK_SUCCESS) && pPhysicalDevice &&
1665 pPresentModes && pPresentModeCount &&
1666 (*pPresentModeCount > 0)) {
1667 // Record the result of this query:
1668 pPhysicalDevice->presentModeCount = *pPresentModeCount;
1669 pPhysicalDevice->pPresentModes = (VkPresentModeKHR *)malloc(*pPresentModeCount * sizeof(VkPresentModeKHR));
1670 if (pPhysicalDevice->pPresentModes) {
1671 for (uint32_t i = 0; i < *pPresentModeCount; i++) {
1672 pPhysicalDevice->pPresentModes[i] = pPresentModes[i];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001673 }
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06001674 } else {
1675 pPhysicalDevice->presentModeCount = 0;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001676 }
1677 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06001678 lock.unlock();
1679
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001680 return result;
1681 }
1682 return VK_ERROR_VALIDATION_FAILED_EXT;
1683}
Ian Elliott0b4d6242015-09-22 10:51:24 -06001684
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001685// This function does the up-front validation work for vkCreateSwapchainKHR(),
Dustin Graves080069b2016-04-05 13:48:15 -06001686// and returns true if a logging callback indicates that the call down the
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001687// chain should be skipped:
Dustin Graves080069b2016-04-05 13:48:15 -06001688static bool validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, VkSwapchainKHR *pSwapchain) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001689 // TODO: Validate cases of re-creating a swapchain (the current code
1690 // assumes a new swapchain is being created).
Dustin Graves080069b2016-04-05 13:48:15 -06001691 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001692 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1693 char fn[] = "vkCreateSwapchainKHR";
Ian Elliott77f46ca2016-05-05 14:10:49 -06001694 SwpDevice *pDevice = NULL;
1695 {
1696 auto it = my_data->deviceMap.find(device);
1697 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
1698 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001699
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001700 // Validate that the swapchain extension was enabled:
1701 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001702 return LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
1703 "%s() called even though the %s extension was not enabled for this VkDevice.", fn,
1704 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001705 }
1706 if (!pCreateInfo) {
Ian Elliott432a3172016-05-09 12:33:47 -06001707 return LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001708 } else {
1709 if (pCreateInfo->sType != VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001710 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001711 "VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR");
1712 }
1713 if (pCreateInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001714 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001715 }
1716 }
1717 if (!pSwapchain) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001718 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchain");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001719 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001720
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001721 // Keep around a useful pointer to pPhysicalDevice:
1722 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001723
Mark Lobodzinskid40b2db2016-02-25 13:56:57 -07001724 // Validate pCreateInfo values with result of
1725 // vkGetPhysicalDeviceQueueFamilyProperties
1726 if (pPhysicalDevice && pPhysicalDevice->gotQueueFamilyPropertyCount) {
Michael Mc Donnell75ecdb72016-04-03 14:47:51 -07001727 for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001728 if (pCreateInfo->pQueueFamilyIndices[i] >= pPhysicalDevice->numOfQueueFamilies) {
1729 skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
1730 "VkPhysicalDevice", pCreateInfo->pQueueFamilyIndices[i],
1731 pPhysicalDevice->numOfQueueFamilies);
Mark Lobodzinskid40b2db2016-02-25 13:56:57 -07001732 }
1733 }
1734 }
1735
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001736 // Validate pCreateInfo values with the results of
1737 // vkGetPhysicalDeviceSurfaceCapabilitiesKHR():
1738 if (!pPhysicalDevice || !pPhysicalDevice->gotSurfaceCapabilities) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001739 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001740 "%s() called before calling "
1741 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1742 fn);
1743 } else if (pCreateInfo) {
1744 // Validate pCreateInfo->surface to make sure that
1745 // vkGetPhysicalDeviceSurfaceSupportKHR() reported this as a supported
1746 // surface:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001747 SwpSurface *pSurface = ((pPhysicalDevice) ? pPhysicalDevice->supportedSurfaces[pCreateInfo->surface] : NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001748 if (!pSurface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001749 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001750 "%s() called with pCreateInfo->surface that "
1751 "was not returned by "
1752 "vkGetPhysicalDeviceSurfaceSupportKHR() "
1753 "for the device.",
1754 fn);
1755 }
Ian Elliott4f147fc2016-01-20 08:52:08 -07001756
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001757 // Validate pCreateInfo->minImageCount against
1758 // VkSurfaceCapabilitiesKHR::{min|max}ImageCount:
1759 VkSurfaceCapabilitiesKHR *pCapabilities = &pPhysicalDevice->surfaceCapabilities;
1760 if ((pCreateInfo->minImageCount < pCapabilities->minImageCount) ||
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001761 ((pCapabilities->maxImageCount > 0) && (pCreateInfo->minImageCount > pCapabilities->maxImageCount))) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001762 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001763 SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT, "%s() called with pCreateInfo->minImageCount "
1764 "= %d, which is outside the bounds returned "
1765 "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. "
1766 "minImageCount = %d, maxImageCount = %d).",
1767 fn, pCreateInfo->minImageCount, pCapabilities->minImageCount, pCapabilities->maxImageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001768 }
1769 // Validate pCreateInfo->imageExtent against
1770 // VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
1771 if ((pCapabilities->currentExtent.width == -1) &&
1772 ((pCreateInfo->imageExtent.width < pCapabilities->minImageExtent.width) ||
1773 (pCreateInfo->imageExtent.width > pCapabilities->maxImageExtent.width) ||
1774 (pCreateInfo->imageExtent.height < pCapabilities->minImageExtent.height) ||
1775 (pCreateInfo->imageExtent.height > pCapabilities->maxImageExtent.height))) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001776 skipCall |= LOG_ERROR(
1777 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS,
1778 "%s() called with pCreateInfo->imageExtent = "
1779 "(%d,%d), which is outside the bounds "
1780 "returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): "
1781 "currentExtent = (%d,%d), minImageExtent = "
1782 "(%d,%d), maxImageExtent = (%d,%d).",
1783 fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, pCapabilities->currentExtent.width,
1784 pCapabilities->currentExtent.height, pCapabilities->minImageExtent.width, pCapabilities->minImageExtent.height,
1785 pCapabilities->maxImageExtent.width, pCapabilities->maxImageExtent.height);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001786 }
1787 if ((pCapabilities->currentExtent.width != -1) &&
1788 ((pCreateInfo->imageExtent.width != pCapabilities->currentExtent.width) ||
1789 (pCreateInfo->imageExtent.height != pCapabilities->currentExtent.height))) {
1790 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001791 SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN, "%s() called with pCreateInfo->imageExtent = "
1792 "(%d,%d), which is not equal to the "
1793 "currentExtent = (%d,%d) returned by "
1794 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
1795 fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height,
1796 pCapabilities->currentExtent.width, pCapabilities->currentExtent.height);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001797 }
1798 // Validate pCreateInfo->preTransform has one bit set (1st two
1799 // lines of if-statement), which bit is also set in
1800 // VkSurfaceCapabilitiesKHR::supportedTransforms (3rd line of if-statement):
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001801 if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) ||
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001802 !(pCreateInfo->preTransform & pCapabilities->supportedTransforms)) {
1803 // This is an error situation; one for which we'd like to give
1804 // the developer a helpful, multi-line error message. Build it
1805 // up a little at a time, and then log it:
1806 std::string errorString = "";
1807 char str[1024];
1808 // Here's the first part of the message:
1809 sprintf(str, "%s() called with a non-supported "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001810 "pCreateInfo->preTransform (i.e. %s). "
1811 "Supported values are:\n",
1812 fn, surfaceTransformStr(pCreateInfo->preTransform));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001813 errorString += str;
1814 for (int i = 0; i < 32; i++) {
1815 // Build up the rest of the message:
1816 if ((1 << i) & pCapabilities->supportedTransforms) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001817 const char *newStr = surfaceTransformStr((VkSurfaceTransformFlagBitsKHR)(1 << i));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001818 sprintf(str, " %s\n", newStr);
1819 errorString += str;
1820 }
1821 }
1822 // Log the message that we've built up:
Mark Lobodzinskia4cbbcd2016-05-24 15:44:50 -06001823 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1824 reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM, LAYER_NAME,
1825 "%s", errorString.c_str());
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001826 }
1827 // Validate pCreateInfo->compositeAlpha has one bit set (1st two
1828 // lines of if-statement), which bit is also set in
1829 // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha (3rd line of if-statement):
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001830 if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) ||
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001831 !((pCreateInfo->compositeAlpha) & pCapabilities->supportedCompositeAlpha)) {
1832 // This is an error situation; one for which we'd like to give
1833 // the developer a helpful, multi-line error message. Build it
1834 // up a little at a time, and then log it:
1835 std::string errorString = "";
1836 char str[1024];
1837 // Here's the first part of the message:
1838 sprintf(str, "%s() called with a non-supported "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001839 "pCreateInfo->compositeAlpha (i.e. %s). "
1840 "Supported values are:\n",
1841 fn, surfaceCompositeAlphaStr(pCreateInfo->compositeAlpha));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001842 errorString += str;
1843 for (int i = 0; i < 32; i++) {
1844 // Build up the rest of the message:
1845 if ((1 << i) & pCapabilities->supportedCompositeAlpha) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001846 const char *newStr = surfaceCompositeAlphaStr((VkCompositeAlphaFlagBitsKHR)(1 << i));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001847 sprintf(str, " %s\n", newStr);
1848 errorString += str;
1849 }
1850 }
1851 // Log the message that we've built up:
Mark Lobodzinskia4cbbcd2016-05-24 15:44:50 -06001852 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
1853 reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA,
1854 LAYER_NAME, "%s", errorString.c_str());
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001855 }
David McFarlande22cfb02016-05-20 18:26:28 -03001856 // Validate pCreateInfo->imageArrayLayers against
1857 // VkSurfaceCapabilitiesKHR::maxImageArrayLayers:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001858 if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > pCapabilities->maxImageArrayLayers)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001859 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
David McFarlande22cfb02016-05-20 18:26:28 -03001860 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_LAYERS, "%s() called with a non-supported "
1861 "pCreateInfo->imageArrayLayers (i.e. %d). "
1862 "Minimum value is 1, maximum value is %d.",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001863 fn, pCreateInfo->imageArrayLayers, pCapabilities->maxImageArrayLayers);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001864 }
1865 // Validate pCreateInfo->imageUsage against
1866 // VkSurfaceCapabilitiesKHR::supportedUsageFlags:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001867 if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & pCapabilities->supportedUsageFlags)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001868 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001869 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS, "%s() called with a non-supported "
1870 "pCreateInfo->imageUsage (i.e. 0x%08x)."
1871 " Supported flag bits are 0x%08x.",
1872 fn, pCreateInfo->imageUsage, pCapabilities->supportedUsageFlags);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001873 }
1874 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001875
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001876 // Validate pCreateInfo values with the results of
1877 // vkGetPhysicalDeviceSurfaceFormatsKHR():
1878 if (!pPhysicalDevice || !pPhysicalDevice->surfaceFormatCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001879 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001880 "%s() called before calling "
1881 "vkGetPhysicalDeviceSurfaceFormatsKHR().",
1882 fn);
1883 } else if (pCreateInfo) {
1884 // Validate pCreateInfo->imageFormat against
1885 // VkSurfaceFormatKHR::format:
1886 bool foundFormat = false;
1887 bool foundColorSpace = false;
1888 bool foundMatch = false;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001889 for (uint32_t i = 0; i < pPhysicalDevice->surfaceFormatCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001890 if (pCreateInfo->imageFormat == pPhysicalDevice->pSurfaceFormats[i].format) {
1891 // Validate pCreateInfo->imageColorSpace against
1892 // VkSurfaceFormatKHR::colorSpace:
1893 foundFormat = true;
1894 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1895 foundMatch = true;
1896 break;
1897 }
1898 } else {
1899 if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
1900 foundColorSpace = true;
1901 }
1902 }
1903 }
1904 if (!foundMatch) {
1905 if (!foundFormat) {
1906 if (!foundColorSpace) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001907 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1908 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP, "%s() called with neither a "
1909 "supported pCreateInfo->imageFormat "
1910 "(i.e. %d) nor a supported "
1911 "pCreateInfo->imageColorSpace "
1912 "(i.e. %d).",
1913 fn, pCreateInfo->imageFormat, pCreateInfo->imageColorSpace);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001914 } else {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001915 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1916 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT, "%s() called with a non-supported "
1917 "pCreateInfo->imageFormat (i.e. %d).",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001918 fn, pCreateInfo->imageFormat);
1919 }
1920 } else if (!foundColorSpace) {
1921 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001922 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE, "%s() called with a non-supported "
1923 "pCreateInfo->imageColorSpace (i.e. %d).",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001924 fn, pCreateInfo->imageColorSpace);
1925 }
1926 }
1927 }
Ian Elliottf7f8ff02015-12-30 14:55:41 -07001928
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001929 // Validate pCreateInfo values with the results of
1930 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1931 if (!pPhysicalDevice || !pPhysicalDevice->presentModeCount) {
szdarkhackfb287d32016-03-12 18:41:19 +02001932 if (!pCreateInfo || (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR)) {
1933 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
1934 "%s() called before calling "
1935 "vkGetPhysicalDeviceSurfacePresentModesKHR().",
1936 fn);
1937 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001938 } else if (pCreateInfo) {
1939 // Validate pCreateInfo->presentMode against
1940 // vkGetPhysicalDeviceSurfacePresentModesKHR():
1941 bool foundMatch = false;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001942 for (uint32_t i = 0; i < pPhysicalDevice->presentModeCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001943 if (pPhysicalDevice->pPresentModes[i] == pCreateInfo->presentMode) {
1944 foundMatch = true;
1945 break;
1946 }
1947 }
1948 if (!foundMatch) {
1949 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001950 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE, "%s() called with a non-supported "
1951 "pCreateInfo->presentMode (i.e. %s).",
1952 fn, presentModeStr(pCreateInfo->presentMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001953 }
1954 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001955
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001956 // Validate pCreateInfo->imageSharingMode and related values:
1957 if (pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001958 if ((pCreateInfo->queueFamilyIndexCount <= 1) || !pCreateInfo->pQueueFamilyIndices) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001959 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001960 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_VALUES, "%s() called with a supported "
baldurk209ccda2016-05-05 16:31:05 +02001961 "pCreateInfo->sharingMode of (i.e. %s), "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001962 "but with a bad value(s) for "
1963 "pCreateInfo->queueFamilyIndexCount or "
1964 "pCreateInfo->pQueueFamilyIndices).",
1965 fn, sharingModeStr(pCreateInfo->imageSharingMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001966 }
1967 } else if (pCreateInfo->imageSharingMode != VK_SHARING_MODE_EXCLUSIVE) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001968 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 -07001969 "%s() called with a non-supported "
1970 "pCreateInfo->imageSharingMode (i.e. %s).",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001971 fn, sharingModeStr(pCreateInfo->imageSharingMode));
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001972 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001973
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001974 // Validate pCreateInfo->clipped:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001975 if (pCreateInfo && (pCreateInfo->clipped != VK_FALSE) && (pCreateInfo->clipped != VK_TRUE)) {
1976 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_BAD_BOOL,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001977 "%s() called with a VkBool32 value that is "
1978 "neither VK_TRUE nor VK_FALSE, but has the "
1979 "numeric value of %d.",
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001980 fn, pCreateInfo->clipped);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001981 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001982
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001983 // Validate pCreateInfo->oldSwapchain:
1984 if (pCreateInfo && pCreateInfo->oldSwapchain) {
Ian Elliott77f46ca2016-05-05 14:10:49 -06001985 SwpSwapchain *pOldSwapchain = NULL;
1986 {
1987 auto it = my_data->swapchainMap.find(pCreateInfo->oldSwapchain);
1988 pOldSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
1989 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001990 if (pOldSwapchain) {
1991 if (device != pOldSwapchain->pDevice->device) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001992 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1993 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE, "%s() called with a different VkDevice "
1994 "than the VkSwapchainKHR was created with.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001995 __FUNCTION__);
1996 }
1997 if (pCreateInfo->surface != pOldSwapchain->pSurface->surface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07001998 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
1999 SWAPCHAIN_CREATE_SWAP_DIFF_SURFACE, "%s() called with pCreateInfo->oldSwapchain "
2000 "that has a different VkSurfaceKHR than "
2001 "pCreateInfo->surface.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002002 fn);
2003 }
2004 } else {
2005 // TBD: Leave this in (not sure object_track will check this)?
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002006 skipCall |=
2007 LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pCreateInfo->oldSwapchain, "VkSwapchainKHR");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002008 }
2009 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002010
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002011 return skipCall;
2012}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002013
Chia-I Wufccbfe42016-04-28 14:01:30 +08002014VKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
2015 const VkAllocationCallbacks *pAllocator,
2016 VkSwapchainKHR *pSwapchain) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002017 VkResult result = VK_SUCCESS;
2018 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002019 std::unique_lock<std::mutex> lock(global_lock);
Dustin Graves080069b2016-04-05 13:48:15 -06002020 bool skipCall = validateCreateSwapchainKHR(device, pCreateInfo, pSwapchain);
Ian Elliott970a2bd2016-06-21 11:08:43 -06002021 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002022
Dustin Graves080069b2016-04-05 13:48:15 -06002023 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002024 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002025 result = my_data->device_dispatch_table->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002026 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002027
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002028 if (result == VK_SUCCESS) {
2029 // Remember the swapchain's handle, and link it to the device:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002030 SwpDevice *pDevice = NULL;
2031 {
2032 auto it = my_data->deviceMap.find(device);
2033 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2034 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002035
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002036 my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
2037 if (pDevice) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002038 pDevice->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002039 }
2040 my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
2041 my_data->swapchainMap[*pSwapchain].imageCount = 0;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002042 my_data->swapchainMap[*pSwapchain].usedAllocatorToCreate = (pAllocator != NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002043 // Store a pointer to the surface
2044 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002045 SwpInstance *pInstance = (pPhysicalDevice) ? pPhysicalDevice->pInstance : NULL;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002046 layer_data *my_instance_data =
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002047 ((pInstance) ? get_my_data_ptr(get_dispatch_key(pInstance->instance), layer_data_map) : NULL);
2048 SwpSurface *pSurface = ((my_data && pCreateInfo) ? &my_instance_data->surfaceMap[pCreateInfo->surface] : NULL);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002049 my_data->swapchainMap[*pSwapchain].pSurface = pSurface;
2050 if (pSurface) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002051 pSurface->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002052 }
2053 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002054 lock.unlock();
2055
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002056 return result;
2057 }
2058 return VK_ERROR_VALIDATION_FAILED_EXT;
2059}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002060
Chia-I Wufccbfe42016-04-28 14:01:30 +08002061VKAPI_ATTR void VKAPI_CALL
2062DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002063 // TODOs:
2064 //
2065 // - Implement a check for validity language that reads: All uses of
Ian Elliotta5d13a92016-04-07 09:05:45 -06002066 // presentable images acquired from pname:swapchain must: have completed
2067 // execution
Dustin Graves080069b2016-04-05 13:48:15 -06002068 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002069 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002070 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002071 SwpDevice *pDevice = NULL;
2072 {
2073 auto it = my_data->deviceMap.find(device);
2074 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2075 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07002076
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002077 // Validate that the swapchain extension was enabled:
2078 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002079 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2080 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2081 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002082 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06002083
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002084 // Regardless of skipCall value, do some internal cleanup:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002085 SwpSwapchain *pSwapchain = NULL;
2086 {
2087 auto it = my_data->swapchainMap.find(swapchain);
2088 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2089 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002090 if (pSwapchain) {
2091 // Delete the SwpSwapchain associated with this swapchain:
2092 if (pSwapchain->pDevice) {
2093 pSwapchain->pDevice->swapchains.erase(swapchain);
2094 if (device != pSwapchain->pDevice->device) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002095 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002096 "%s() called with a different VkDevice than the "
2097 "VkSwapchainKHR was created with.",
2098 __FUNCTION__);
2099 }
2100 }
2101 if (pSwapchain->pSurface) {
2102 pSwapchain->pSurface->swapchains.erase(swapchain);
2103 }
2104 if (pSwapchain->imageCount) {
2105 pSwapchain->images.clear();
2106 }
2107 if ((pAllocator != NULL) != pSwapchain->usedAllocatorToCreate) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002108 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002109 "%s() called with incompatible pAllocator from when "
2110 "the object was created.",
2111 __FUNCTION__);
2112 }
2113 my_data->swapchainMap.erase(swapchain);
2114 }
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002115 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002116
Dustin Graves080069b2016-04-05 13:48:15 -06002117 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002118 // Call down the call chain:
2119 my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator);
2120 }
2121}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002122
Chia-I Wufccbfe42016-04-28 14:01:30 +08002123VKAPI_ATTR VkResult VKAPI_CALL
2124GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002125 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06002126 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002127 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002128 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002129 SwpDevice *pDevice = NULL;
2130 {
2131 auto it = my_data->deviceMap.find(device);
2132 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2133 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07002134
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002135 // Validate that the swapchain extension was enabled:
2136 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002137 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2138 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2139 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002140 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06002141 SwpSwapchain *pSwapchain = NULL;
2142 {
2143 auto it = my_data->swapchainMap.find(swapchain);
2144 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2145 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002146 if (!pSwapchainImageCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002147 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchainImageCount");
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06002148 } else if (pSwapchain && pSwapchainImages) {
2149 // Compare the preliminary value of *pSwapchainImageCount with the
2150 // value this time:
2151 if (pSwapchain->imageCount == 0) {
2152 // Since we haven't recorded a preliminary value of
2153 // *pSwapchainImageCount, that likely means that the application
2154 // didn't previously call this function with a NULL value of
2155 // pSwapchainImages:
2156 skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
2157 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2158 device, "pSwapchainImageCount", "pSwapchainImages");
2159 } else if (*pSwapchainImageCount > pSwapchain->imageCount) {
2160 skipCall |= LOG_ERROR_INVALID_COUNT(
2161 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
2162 device, "pSwapchainImageCount", "pSwapchainImages",
2163 *pSwapchainImageCount, pSwapchain->imageCount);
2164 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002165 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002166 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002167
Dustin Graves080069b2016-04-05 13:48:15 -06002168 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002169 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002170 result = my_data->device_dispatch_table->GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002171 lock.lock();
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002172
Ian Elliott32311832016-02-04 08:17:18 -07002173 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002174 {
2175 auto it = my_data->swapchainMap.find(swapchain);
2176 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2177 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002178 if ((result == VK_SUCCESS) && pSwapchain && !pSwapchainImages && pSwapchainImageCount) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002179 // Record the result of this preliminary query:
2180 pSwapchain->imageCount = *pSwapchainImageCount;
Ian Elliottfdf3ffa2016-05-05 14:06:53 -06002181 } else if ((result == VK_SUCCESS) && pSwapchain && pSwapchainImages &&
2182 pSwapchainImageCount && (*pSwapchainImageCount > 0)) {
2183 // Record the images and their state:
2184 pSwapchain->imageCount = *pSwapchainImageCount;
2185 for (uint32_t i = 0; i < *pSwapchainImageCount; i++) {
2186 pSwapchain->images[i].image = pSwapchainImages[i];
2187 pSwapchain->images[i].pSwapchain = pSwapchain;
2188 pSwapchain->images[i].acquiredByApp = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002189 }
2190 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002191 lock.unlock();
2192
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002193 return result;
2194 }
2195 return VK_ERROR_VALIDATION_FAILED_EXT;
2196}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002197
Chia-I Wufccbfe42016-04-28 14:01:30 +08002198VKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
2199 VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002200 // TODOs:
2201 //
2202 // - Address the timeout. Possibilities include looking at the state of the
2203 // swapchain's images, depending on the timeout value.
2204 // - Implement a check for validity language that reads: If pname:semaphore is
2205 // not sname:VK_NULL_HANDLE it must: be unsignalled
2206 // - Implement a check for validity language that reads: If pname:fence is not
2207 // sname:VK_NULL_HANDLE it must: be unsignalled and mustnot: be associated
2208 // with any other queue command that has not yet completed execution on that
2209 // queue
2210 // - Record/update the state of the swapchain, in case an error occurs
2211 // (e.g. VK_ERROR_OUT_OF_DATE_KHR).
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002212 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06002213 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002214 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002215 std::unique_lock<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002216 SwpDevice *pDevice = NULL;
2217 {
2218 auto it = my_data->deviceMap.find(device);
2219 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2220 }
Ian Elliott8b9e2562016-01-05 13:00:50 -07002221
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002222 // Validate that the swapchain extension was enabled:
2223 if (pDevice && !pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002224 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
2225 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2226 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002227 }
Ian Elliottfa8f0322016-03-23 08:28:54 -06002228 if ((semaphore == VK_NULL_HANDLE) && (fence == VK_NULL_HANDLE)) {
Ian Elliott5da0c962016-03-23 11:13:09 -06002229 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_NO_SYNC_FOR_ACQUIRE,
2230 "%s() called with both the semaphore and fence parameters set to "
Jamie Madillcc4e9322016-05-04 12:20:15 -07002231 "VK_NULL_HANDLE (at least one should be used).", __FUNCTION__);
Ian Elliottfa8f0322016-03-23 08:28:54 -06002232 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06002233 SwpSwapchain *pSwapchain = NULL;
2234 {
2235 auto it = my_data->swapchainMap.find(swapchain);
2236 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2237 }
Ian Elliott5c680282016-04-06 14:29:56 -06002238 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
2239 if (pSwapchain && pPhysicalDevice && pPhysicalDevice->gotSurfaceCapabilities) {
2240 // Look to see if the application has already acquired the maximum
2241 // number of images, and this will push it past the spec-defined
2242 // limits:
2243 uint32_t minImageCount = pPhysicalDevice->surfaceCapabilities.minImageCount;
2244 uint32_t imagesAcquiredByApp = 0;
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002245 for (uint32_t i = 0; i < pSwapchain->imageCount; i++) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002246 if (pSwapchain->images[i].acquiredByApp) {
Ian Elliott5c680282016-04-06 14:29:56 -06002247 imagesAcquiredByApp++;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002248 }
2249 }
Ian Elliott5c680282016-04-06 14:29:56 -06002250 if (imagesAcquiredByApp > (pSwapchain->imageCount - minImageCount)) {
2251 skipCall |= LOG_ERROR(
2252 VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
2253 swapchain, "VkSwapchainKHR",
2254 SWAPCHAIN_APP_ACQUIRES_TOO_MANY_IMAGES,
2255 "%s() called when it cannot succeed. The application has "
2256 "acquired %d image(s) that have not yet been presented. The "
2257 "maximum number of images that the application can "
2258 "simultaneously acquire from this swapchain (including this "
2259 "call to %s()) is %d. That value is derived by subtracting "
2260 "VkSurfaceCapabilitiesKHR::minImageCount (%d) from the number "
2261 "of images in the swapchain (%d) and adding 1.\n",
2262 __FUNCTION__, imagesAcquiredByApp, __FUNCTION__,
2263 (pSwapchain->imageCount - minImageCount + 1),
2264 minImageCount, pSwapchain->imageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002265 }
2266 }
2267 if (!pImageIndex) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002268 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pImageIndex");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002269 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002270 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002271
Dustin Graves080069b2016-04-05 13:48:15 -06002272 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002273 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002274 result = my_data->device_dispatch_table->AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002275 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002276
Ian Elliott32311832016-02-04 08:17:18 -07002277 // Obtain this pointer again after locking:
Ian Elliott77f46ca2016-05-05 14:10:49 -06002278 {
2279 auto it = my_data->swapchainMap.find(swapchain);
2280 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2281 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002282 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) && pSwapchain) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002283 // Change the state of the image (now acquired by the application):
2284 pSwapchain->images[*pImageIndex].acquiredByApp = true;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002285 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002286 lock.unlock();
2287
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002288 return result;
2289 }
2290 return VK_ERROR_VALIDATION_FAILED_EXT;
2291}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002292
Chia-I Wufccbfe42016-04-28 14:01:30 +08002293VKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002294 // TODOs:
2295 //
2296 // - Implement a check for validity language that reads: Any given element of
2297 // sname:VkSemaphore in pname:pWaitSemaphores must: refer to a prior signal
2298 // of that sname:VkSemaphore that won't be consumed by any other wait on that
2299 // semaphore
2300 // - Record/update the state of the swapchain, in case an error occurs
2301 // (e.g. VK_ERROR_OUT_OF_DATE_KHR).
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002302 VkResult result = VK_SUCCESS;
Dustin Graves080069b2016-04-05 13:48:15 -06002303 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002304 layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002305
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002306 if (!pPresentInfo) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002307 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002308 } else {
2309 if (pPresentInfo->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002310 skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002311 "VK_STRUCTURE_TYPE_PRESENT_INFO_KHR");
2312 }
2313 if (pPresentInfo->pNext != NULL) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002314 skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002315 }
2316 if (!pPresentInfo->swapchainCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002317 skipCall |= LOG_ERROR_ZERO_VALUE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->swapchainCount");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002318 }
2319 if (!pPresentInfo->pSwapchains) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002320 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pSwapchains");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002321 }
2322 if (!pPresentInfo->pImageIndices) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002323 skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pImageIndices");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002324 }
2325 // Note: pPresentInfo->pResults is allowed to be NULL
2326 }
Ian Elliott046ed2c2015-12-30 17:07:17 -07002327
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002328 std::unique_lock<std::mutex> lock(global_lock);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002329 for (uint32_t i = 0; pPresentInfo && (i < pPresentInfo->swapchainCount); i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002330 uint32_t index = pPresentInfo->pImageIndices[i];
Ian Elliott77f46ca2016-05-05 14:10:49 -06002331 SwpSwapchain *pSwapchain = NULL;
2332 {
2333 auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
2334 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2335 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002336 if (pSwapchain) {
2337 if (!pSwapchain->pDevice->swapchainExtensionEnabled) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002338 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, pSwapchain->pDevice, "VkDevice",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002339 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002340 "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
2341 VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002342 }
2343 if (index >= pSwapchain->imageCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002344 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
2345 SWAPCHAIN_INDEX_TOO_LARGE, "%s() called for an index that is too "
2346 "large (i.e. %d). There are only %d "
2347 "images in this VkSwapchainKHR.\n",
2348 __FUNCTION__, index, pSwapchain->imageCount);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002349 } else {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002350 if (!pSwapchain->images[index].acquiredByApp) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002351 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i],
2352 "VkSwapchainKHR", SWAPCHAIN_INDEX_NOT_IN_USE, "%s() returned an index (i.e. %d) "
Ian Elliotta5d13a92016-04-07 09:05:45 -06002353 "for an image that is not acquired by "
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002354 "the application.",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002355 __FUNCTION__, index);
2356 }
2357 }
Ian Elliott77f46ca2016-05-05 14:10:49 -06002358 SwpQueue *pQueue = NULL;
2359 {
2360 auto it = my_data->queueMap.find(queue);
2361 pQueue = (it == my_data->queueMap.end()) ? NULL : &it->second;
2362 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002363 SwpSurface *pSurface = pSwapchain->pSurface;
2364 if (pQueue && pSurface && pSurface->numQueueFamilyIndexSupport) {
2365 uint32_t queueFamilyIndex = pQueue->queueFamilyIndex;
2366 // Note: the 1st test is to ensure queueFamilyIndex is in range,
2367 // and the 2nd test is the validation check:
2368 if ((pSurface->numQueueFamilyIndexSupport > queueFamilyIndex) &&
2369 (!pSurface->pQueueFamilyIndexSupport[queueFamilyIndex])) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002370 skipCall |=
2371 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
2372 SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, "%s() called with a swapchain whose "
2373 "surface is not supported for "
2374 "presention on this device with the "
2375 "queueFamilyIndex (i.e. %d) of the "
2376 "given queue.",
2377 __FUNCTION__, queueFamilyIndex);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002378 }
2379 }
2380 }
2381 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002382 lock.unlock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002383
Dustin Graves080069b2016-04-05 13:48:15 -06002384 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002385 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002386 result = my_data->device_dispatch_table->QueuePresentKHR(queue, pPresentInfo);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002387 lock.lock();
Ian Elliott0b4d6242015-09-22 10:51:24 -06002388
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002389 if (pPresentInfo && ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR))) {
2390 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002391 int index = pPresentInfo->pImageIndices[i];
Ian Elliott77f46ca2016-05-05 14:10:49 -06002392 SwpSwapchain *pSwapchain = NULL;
2393 {
2394 auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
2395 pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
2396 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002397 if (pSwapchain) {
Ian Elliotta5d13a92016-04-07 09:05:45 -06002398 // Change the state of the image (no longer acquired by the
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002399 // application):
Ian Elliotta5d13a92016-04-07 09:05:45 -06002400 pSwapchain->images[index].acquiredByApp = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002401 }
2402 }
2403 }
Ian Elliott970a2bd2016-06-21 11:08:43 -06002404 lock.unlock();
2405
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002406 return result;
2407 }
2408 return VK_ERROR_VALIDATION_FAILED_EXT;
2409}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002410
Chia-I Wufccbfe42016-04-28 14:01:30 +08002411VKAPI_ATTR void VKAPI_CALL
2412GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
Dustin Graves080069b2016-04-05 13:48:15 -06002413 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002414 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliottc4db6952016-01-21 14:29:45 -07002415
Dustin Graves080069b2016-04-05 13:48:15 -06002416 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002417 // Call down the call chain:
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002418 my_data->device_dispatch_table->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
Ian Elliottc4db6952016-01-21 14:29:45 -07002419
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002420 // Remember the queue's handle, and link it to the device:
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002421 std::lock_guard<std::mutex> lock(global_lock);
Ian Elliott77f46ca2016-05-05 14:10:49 -06002422 SwpDevice *pDevice = NULL;
2423 {
2424 auto it = my_data->deviceMap.find(device);
2425 pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
2426 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002427 my_data->queueMap[&pQueue].queue = *pQueue;
2428 if (pDevice) {
2429 pDevice->queues[*pQueue] = &my_data->queueMap[*pQueue];
2430 }
2431 my_data->queueMap[&pQueue].pDevice = pDevice;
2432 my_data->queueMap[&pQueue].queueFamilyIndex = queueFamilyIndex;
2433 }
2434}
Ian Elliottc4db6952016-01-21 14:29:45 -07002435
Chia-I Wufccbfe42016-04-28 14:01:30 +08002436VKAPI_ATTR VkResult VKAPI_CALL
2437CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2438 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002439 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002440 VkResult result =
2441 my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002442 if (VK_SUCCESS == result) {
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002443 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski97c4d512016-05-19 15:27:18 -06002444 result = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002445 }
2446 return result;
2447}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002448
Chia-I Wufccbfe42016-04-28 14:01:30 +08002449VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance,
2450 VkDebugReportCallbackEXT msgCallback,
2451 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002452 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
2453 my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Jeremy Hayes9de0bd72016-04-13 11:57:20 -06002454 std::lock_guard<std::mutex> lock(global_lock);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002455 layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
2456}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002457
Chia-I Wufccbfe42016-04-28 14:01:30 +08002458VKAPI_ATTR void VKAPI_CALL
2459DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
2460 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002461 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002462 my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix,
2463 pMsg);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002464}
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07002465
Chia-I Wub02600c2016-05-20 07:11:22 +08002466VKAPI_ATTR VkResult VKAPI_CALL
2467EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
2468 return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
2469}
2470
2471VKAPI_ATTR VkResult VKAPI_CALL
2472EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
2473 return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
2474}
2475
2476VKAPI_ATTR VkResult VKAPI_CALL
2477EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
2478 if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
2479 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
2480
2481 return VK_ERROR_LAYER_NOT_PRESENT;
2482}
2483
Chia-I Wufccbfe42016-04-28 14:01:30 +08002484VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
2485 const char *pLayerName, uint32_t *pCount,
2486 VkExtensionProperties *pProperties) {
Chia-I Wu2b481252016-04-28 14:21:13 +08002487 if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
Chia-I Wu045209e2016-04-28 11:21:49 +08002488 return util_GetExtensionProperties(0, nullptr, pCount, pProperties);
Chia-I Wu2b481252016-04-28 14:21:13 +08002489
2490 assert(physicalDevice);
2491
2492 dispatch_key key = get_dispatch_key(physicalDevice);
2493 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
2494 return my_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002495}
2496
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002497static PFN_vkVoidFunction
Chia-I Wu22813c72016-04-28 14:38:57 +08002498intercept_core_instance_command(const char *name);
2499
2500static PFN_vkVoidFunction
2501intercept_khr_surface_command(const char *name, VkInstance instance);
2502
2503static PFN_vkVoidFunction
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002504intercept_core_device_command(const char *name);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002505
Chia-I Wu83245952016-05-05 16:13:19 +08002506static PFN_vkVoidFunction
2507intercept_khr_swapchain_command(const char *name, VkDevice dev);
2508
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002509VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
2510 PFN_vkVoidFunction proc = intercept_core_device_command(funcName);
2511 if (proc)
2512 return proc;
2513
2514 assert(device);
Ian Elliott0b4d6242015-09-22 10:51:24 -06002515
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002516 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06002517
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002518 my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Courtney Goeltzenleuchter1e9e6c82016-03-19 10:38:52 -06002519 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
Chia-I Wu83245952016-05-05 16:13:19 +08002520
2521 proc = intercept_khr_swapchain_command(funcName, device);
2522 if (proc)
2523 return proc;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07002524
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002525 if (pDisp->GetDeviceProcAddr == NULL)
2526 return NULL;
2527 return pDisp->GetDeviceProcAddr(device, funcName);
2528}
Ian Elliott0b4d6242015-09-22 10:51:24 -06002529
Chia-I Wufccbfe42016-04-28 14:01:30 +08002530VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wu22813c72016-04-28 14:38:57 +08002531 PFN_vkVoidFunction proc = intercept_core_instance_command(funcName);
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002532 if (!proc)
2533 proc = intercept_core_device_command(funcName);
2534 if (!proc)
2535 proc = intercept_khr_swapchain_command(funcName, VK_NULL_HANDLE);
Chia-I Wu22813c72016-04-28 14:38:57 +08002536 if (proc)
2537 return proc;
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07002538
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002539 assert(instance);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002540
2541 layer_data *my_data;
2542 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -07002543 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Ian Elliott68124ac2015-10-07 16:18:35 -06002544
Chia-I Wu5ae2f652016-04-28 15:16:59 +08002545 proc = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
2546 if (!proc)
2547 proc = intercept_khr_surface_command(funcName, instance);
Chia-I Wu22813c72016-04-28 14:38:57 +08002548 if (proc)
2549 return proc;
Ian Elliott0b4d6242015-09-22 10:51:24 -06002550
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07002551 if (pTable->GetInstanceProcAddr == NULL)
2552 return NULL;
2553 return pTable->GetInstanceProcAddr(instance, funcName);
2554}
Chia-I Wu045209e2016-04-28 11:21:49 +08002555
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002556static PFN_vkVoidFunction
Chia-I Wu22813c72016-04-28 14:38:57 +08002557intercept_core_instance_command(const char *name) {
2558 static const struct {
2559 const char *name;
2560 PFN_vkVoidFunction proc;
2561 } core_instance_commands[] = {
2562 { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
2563 { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
2564 { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) },
2565 { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
2566 { "vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices) },
Chia-I Wub02600c2016-05-20 07:11:22 +08002567 { "vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties) },
2568 { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
2569 { "vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties) },
Chia-I Wu22813c72016-04-28 14:38:57 +08002570 { "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
2571 { "vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties) },
2572 };
2573
2574 for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
2575 if (!strcmp(core_instance_commands[i].name, name))
2576 return core_instance_commands[i].proc;
2577 }
2578
2579 return nullptr;
2580}
2581
2582static PFN_vkVoidFunction
2583intercept_khr_surface_command(const char *name, VkInstance instance) {
2584 static const struct {
2585 const char *name;
2586 PFN_vkVoidFunction proc;
2587 } khr_surface_commands[] = {
2588#ifdef VK_USE_PLATFORM_ANDROID_KHR
2589 { "vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateAndroidSurfaceKHR) },
2590#endif // VK_USE_PLATFORM_ANDROID_KHR
2591#ifdef VK_USE_PLATFORM_MIR_KHR
2592 { "vkCreateMirSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateMirSurfaceKHR) },
2593 { "vkGetPhysicalDeviceMirPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceMirPresentationSupportKHR) },
2594#endif // VK_USE_PLATFORM_MIR_KHR
2595#ifdef VK_USE_PLATFORM_WAYLAND_KHR
2596 { "vkCreateWaylandSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWaylandSurfaceKHR) },
2597 { "vkGetPhysicalDeviceWaylandPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWaylandPresentationSupportKHR) },
2598#endif // VK_USE_PLATFORM_WAYLAND_KHR
2599#ifdef VK_USE_PLATFORM_WIN32_KHR
2600 { "vkCreateWin32SurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWin32SurfaceKHR) },
2601 { "vkGetPhysicalDeviceWin32PresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWin32PresentationSupportKHR) },
2602#endif // VK_USE_PLATFORM_WIN32_KHR
2603#ifdef VK_USE_PLATFORM_XCB_KHR
2604 { "vkCreateXcbSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXcbSurfaceKHR) },
2605 { "vkGetPhysicalDeviceXcbPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXcbPresentationSupportKHR) },
2606#endif // VK_USE_PLATFORM_XCB_KHR
2607#ifdef VK_USE_PLATFORM_XLIB_KHR
2608 { "vkCreateXlibSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXlibSurfaceKHR) },
2609 { "vkGetPhysicalDeviceXlibPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXlibPresentationSupportKHR) },
2610#endif // VK_USE_PLATFORM_XLIB_KHR
2611 { "vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySurfaceKHR) },
2612 { "vkGetPhysicalDeviceSurfaceSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceSupportKHR) },
2613 { "vkGetPhysicalDeviceSurfaceCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceCapabilitiesKHR) },
2614 { "vkGetPhysicalDeviceSurfaceFormatsKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceFormatsKHR) },
2615 { "vkGetPhysicalDeviceSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfacePresentModesKHR) },
Petros Bantolas2b40be72016-04-15 11:02:59 +01002616 { "vkGetPhysicalDeviceDisplayPropertiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceDisplayPropertiesKHR) },
2617 { "vkGetPhysicalDeviceDisplayPlanePropertiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceDisplayPlanePropertiesKHR) },
2618 { "vkGetDisplayPlaneSupportedDisplaysKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayPlaneSupportedDisplaysKHR) },
2619 { "vkGetDisplayModePropertiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayModePropertiesKHR) },
2620 { "vkCreateDisplayModeKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDisplayModeKHR) },
2621 { "vkGetDisplayPlaneCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetDisplayPlaneCapabilitiesKHR) },
2622 { "vkCreateDisplayPlaneSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateDisplayPlaneSurfaceKHR) },
Chia-I Wu22813c72016-04-28 14:38:57 +08002623 };
2624
2625 // do not check if VK_KHR_*_surface is enabled (why?)
2626
2627 for (size_t i = 0; i < ARRAY_SIZE(khr_surface_commands); i++) {
2628 if (!strcmp(khr_surface_commands[i].name, name))
2629 return khr_surface_commands[i].proc;
2630 }
2631
2632 return nullptr;
2633}
2634
2635static PFN_vkVoidFunction
Chia-I Wu9bc0b582016-04-28 14:38:57 +08002636intercept_core_device_command(const char *name) {
2637 static const struct {
2638 const char *name;
2639 PFN_vkVoidFunction proc;
2640 } core_device_commands[] = {
2641 { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
2642 { "vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice) },
2643 { "vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue) },
2644 };
2645
2646 for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) {
2647 if (!strcmp(core_device_commands[i].name, name))
2648 return core_device_commands[i].proc;
2649 }
2650
2651 return nullptr;
2652}
2653
Chia-I Wu83245952016-05-05 16:13:19 +08002654static PFN_vkVoidFunction
2655intercept_khr_swapchain_command(const char *name, VkDevice dev) {
2656 static const struct {
2657 const char *name;
2658 PFN_vkVoidFunction proc;
2659 } khr_swapchain_commands[] = {
2660 { "vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR) },
2661 { "vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR) },
2662 { "vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR) },
2663 { "vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR) },
2664 { "vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR) },
2665 };
2666
2667 // do not check if VK_KHR_swapchain is enabled (why?)
2668
2669 for (size_t i = 0; i < ARRAY_SIZE(khr_swapchain_commands); i++) {
2670 if (!strcmp(khr_swapchain_commands[i].name, name))
2671 return khr_swapchain_commands[i].proc;
2672 }
2673
2674 return nullptr;
2675}
2676
Chia-I Wu516b5082016-04-28 11:27:46 +08002677} // namespace swapchain
2678
2679// vk_layer_logging.h expects these to be defined
2680
Chia-I Wufccbfe42016-04-28 14:01:30 +08002681VKAPI_ATTR VkResult VKAPI_CALL
Chia-I Wu516b5082016-04-28 11:27:46 +08002682vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2683 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002684 return swapchain::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Chia-I Wu516b5082016-04-28 11:27:46 +08002685}
2686
Chia-I Wufccbfe42016-04-28 14:01:30 +08002687VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance,
Chia-I Wu516b5082016-04-28 11:27:46 +08002688 VkDebugReportCallbackEXT msgCallback,
2689 const VkAllocationCallbacks *pAllocator) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002690 swapchain::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Chia-I Wu516b5082016-04-28 11:27:46 +08002691}
2692
Chia-I Wufccbfe42016-04-28 14:01:30 +08002693VKAPI_ATTR void VKAPI_CALL
Chia-I Wu516b5082016-04-28 11:27:46 +08002694vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
2695 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002696 swapchain::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
Chia-I Wu516b5082016-04-28 11:27:46 +08002697}
2698
Chia-I Wub02600c2016-05-20 07:11:22 +08002699// loader-layer interface v0, just wrappers since there is only a layer
Chia-I Wu516b5082016-04-28 11:27:46 +08002700
Chia-I Wu045209e2016-04-28 11:21:49 +08002701VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2702vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002703 return swapchain::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002704}
2705
2706VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2707vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002708 return swapchain::EnumerateInstanceLayerProperties(pCount, pProperties);
Chia-I Wu045209e2016-04-28 11:21:49 +08002709}
2710
2711VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2712vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002713 // the layer command handles VK_NULL_HANDLE just fine internally
2714 assert(physicalDevice == VK_NULL_HANDLE);
2715 return swapchain::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
Chia-I Wu516b5082016-04-28 11:27:46 +08002716}
2717
2718VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
2719 const char *pLayerName, uint32_t *pCount,
2720 VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +08002721 // the layer command handles VK_NULL_HANDLE just fine internally
2722 assert(physicalDevice == VK_NULL_HANDLE);
Chia-I Wu2b481252016-04-28 14:21:13 +08002723 return swapchain::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
Chia-I Wu516b5082016-04-28 11:27:46 +08002724}
2725
2726VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002727 return swapchain::GetDeviceProcAddr(dev, funcName);
Chia-I Wu516b5082016-04-28 11:27:46 +08002728}
2729
2730VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wufccbfe42016-04-28 14:01:30 +08002731 return swapchain::GetInstanceProcAddr(instance, funcName);
Chia-I Wu045209e2016-04-28 11:21:49 +08002732}