blob: 69ddb97f47416a91846b93a72f47a6f8b0d4209c [file] [log] [blame]
Ian Elliott0b4d6242015-09-22 10:51:24 -06001/*
Ian Elliott0b4d6242015-09-22 10:51:24 -06002 *
Courtney Goeltzenleuchterfcbe16f2015-10-29 13:50:34 -06003 * Copyright (C) 2015 Valve Corporation
Ian Elliott0b4d6242015-09-22 10:51:24 -06004 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060023 * Author: Ian Elliott <ian@lunarg.com>
24 *
Ian Elliott0b4d6242015-09-22 10:51:24 -060025 */
26
Ian Elliottd8c5db12015-10-07 11:32:31 -060027#include <stdio.h>
28#include <string.h>
Mark Lobodzinskib49b6e52015-11-26 10:59:58 -070029#include <vk_loader_platform.h>
Ian Elliotta983e9a2015-12-22 12:18:12 -070030#include <vk_icd.h>
Ian Elliott0b4d6242015-09-22 10:51:24 -060031#include "swapchain.h"
Tobin Ehlis711ff312015-10-29 12:58:13 -060032#include "vk_layer_extension_utils.h"
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070033#include "vk_enum_string_helper.h"
Ian Elliott68124ac2015-10-07 16:18:35 -060034
Ian Elliott0b4d6242015-09-22 10:51:24 -060035// FIXME/TODO: Make sure this layer is thread-safe!
36
Ian Elliott68124ac2015-10-07 16:18:35 -060037
Ian Elliott0b4d6242015-09-22 10:51:24 -060038// The following is for logging error messages:
Ian Elliott68124ac2015-10-07 16:18:35 -060039static std::unordered_map<void *, layer_data *> layer_data_map;
Ian Elliott0b4d6242015-09-22 10:51:24 -060040
Ian Elliott68124ac2015-10-07 16:18:35 -060041template layer_data *get_my_data_ptr<layer_data>(
42 void *data_key,
43 std::unordered_map<void *, layer_data *> &data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -060044
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -070045static const VkExtensionProperties instance_extensions[] = {
46 {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -070047 VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
48 VK_EXT_DEBUG_REPORT_REVISION
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -070049 }
50};
51
52VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
53 const char *pLayerName,
54 uint32_t *pCount,
55 VkExtensionProperties* pProperties)
56{
57 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
58}
59
60static const VkLayerProperties swapchain_global_layers[] = {
61 {
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -070062 "swapchain",
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -070063 VK_API_VERSION,
64 VK_MAKE_VERSION(0, 1, 0),
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -070065 "Validation layer: swapchain",
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -070066 }
67};
68
69VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
70 uint32_t *pCount,
71 VkLayerProperties* pProperties)
72{
73 return util_GetLayerProperties(ARRAY_SIZE(swapchain_global_layers),
74 swapchain_global_layers,
75 pCount, pProperties);
76}
77
Ian Elliotta983e9a2015-12-22 12:18:12 -070078// This function validates a VkSurfaceKHR object:
79static VkBool32 validateSurface(layer_data *my_data, VkSurfaceKHR surface, char *fn)
80{
81 VkBool32 skipCall = VK_FALSE;
82 bool found_error = false;
83
84 SwpSurface *pSurface = &my_data->surfaceMap[surface];
85 if ((pSurface == NULL) || (pSurface->surface != surface)) {
86 found_error = true;
87 } else {
88#if !defined(__ANDROID__)
89 VkIcdSurfaceBase *pIcdSurface = (VkIcdSurfaceBase *) surface;
90 if (pSurface->platform != pIcdSurface->platform) {
91 found_error = true;
92 }
93#else // !defined(__ANDROID__)
94 if (pSurface->platform != VK_ICD_WSI_PLATFORM_ANDROID) {
95 found_error = true;
96 }
97#endif // !defined(__ANDROID__)
98 }
99 if (found_error) {
Ian Elliott1bf155f2015-12-29 17:35:46 -0700100 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT, surface, "VkSurfaceKHR",
Ian Elliotta983e9a2015-12-22 12:18:12 -0700101 SWAPCHAIN_INVALID_HANDLE,
102 "%s() called with an invalid surface object.",
103 fn);
104 }
105 return skipCall;
106}
Ian Elliott0b4d6242015-09-22 10:51:24 -0600107
Ian Elliott0b4d6242015-09-22 10:51:24 -0600108static void createDeviceRegisterExtensions(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, VkDevice device)
109{
110 uint32_t i;
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700111 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
112 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600113
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700114 VkLayerDispatchTable *pDisp = my_device_data->device_dispatch_table;
115 PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr;
116
117 pDisp->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR) gpa(device, "vkCreateSwapchainKHR");
118 pDisp->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR) gpa(device, "vkDestroySwapchainKHR");
119 pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR) gpa(device, "vkGetSwapchainImagesKHR");
120 pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR) gpa(device, "vkAcquireNextImageKHR");
121 pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR) gpa(device, "vkQueuePresentKHR");
122
123 SwpPhysicalDevice *pPhysicalDevice = &my_instance_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600124 if (pPhysicalDevice) {
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700125 my_device_data->deviceMap[device].pPhysicalDevice = pPhysicalDevice;
126 pPhysicalDevice->pDevice = &my_device_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600127 } else {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700128 log_msg(my_instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
Mark Lobodzinski80e774f2016-01-04 15:54:59 -0700129 (uint64_t)physicalDevice , __LINE__, SWAPCHAIN_INVALID_HANDLE, "Swapchain",
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700130 "vkCreateDevice() called with a non-valid VkPhysicalDevice.");
Ian Elliott0b4d6242015-09-22 10:51:24 -0600131 }
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700132 my_device_data->deviceMap[device].device = device;
Ian Elliott427058f2015-12-29 16:45:49 -0700133 my_device_data->deviceMap[device].swapchainExtensionEnabled = false;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600134
135 // Record whether the WSI device extension was enabled for this VkDevice.
136 // No need to check if the extension was advertised by
137 // vkEnumerateDeviceExtensionProperties(), since the loader handles that.
Chia-I Wud50a7d72015-10-26 20:48:51 +0800138 for (i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Ian Elliott1dcd1092015-11-17 17:29:40 -0700139 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600140
Ian Elliott427058f2015-12-29 16:45:49 -0700141 my_device_data->deviceMap[device].swapchainExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600142 }
143 }
144}
145
146static void createInstanceRegisterExtensions(const VkInstanceCreateInfo* pCreateInfo, VkInstance instance)
147{
148 uint32_t i;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600149 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
150 VkLayerInstanceDispatchTable *pDisp = my_data->instance_dispatch_table;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600151 PFN_vkGetInstanceProcAddr gpa = pDisp->GetInstanceProcAddr;
Ian Elliotta983e9a2015-12-22 12:18:12 -0700152#ifdef VK_USE_PLATFORM_ANDROID_KHR
153 pDisp->CreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR) gpa(instance, "vkCreateAndroidSurfaceKHR");
154#endif // VK_USE_PLATFORM_ANDROID_KHR
155#ifdef VK_USE_PLATFORM_MIR_KHR
156 pDisp->CreateMirSurfaceKHR = (PFN_vkCreateMirSurfaceKHR) gpa(instance, "vkCreateMirSurfaceKHR");
157#endif // VK_USE_PLATFORM_MIR_KHR
158#ifdef VK_USE_PLATFORM_WAYLAND_KHR
159 pDisp->CreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR) gpa(instance, "vkCreateWaylandSurfaceKHR");
160#endif // VK_USE_PLATFORM_WAYLAND_KHR
161#ifdef VK_USE_PLATFORM_WIN32_KHR
162 pDisp->CreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR) gpa(instance, "vkCreateWin32SurfaceKHR");
163#endif // VK_USE_PLATFORM_WIN32_KHR
164#ifdef VK_USE_PLATFORM_XCB_KHR
165 pDisp->CreateXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR) gpa(instance, "vkCreateXcbSurfaceKHR");
166#endif // VK_USE_PLATFORM_XCB_KHR
167#ifdef VK_USE_PLATFORM_XLIB_KHR
168 pDisp->CreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR) gpa(instance, "vkCreateXlibSurfaceKHR");
169#endif // VK_USE_PLATFORM_XLIB_KHR
170 pDisp->DestroySurfaceKHR = (PFN_vkDestroySurfaceKHR) gpa(instance, "vkDestroySurfaceKHR");
Ian Elliott0b4d6242015-09-22 10:51:24 -0600171 pDisp->GetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceSupportKHR");
Ian Elliott27d39c72015-11-20 16:39:34 -0700172 pDisp->GetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
173 pDisp->GetPhysicalDeviceSurfaceFormatsKHR = (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR");
174 pDisp->GetPhysicalDeviceSurfacePresentModesKHR = (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR) gpa(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR");
Ian Elliott0b4d6242015-09-22 10:51:24 -0600175
Ian Elliott1dcd1092015-11-17 17:29:40 -0700176 // Remember this instance, and whether the VK_KHR_surface extension
Ian Elliott0b4d6242015-09-22 10:51:24 -0600177 // was enabled for it:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600178 my_data->instanceMap[instance].instance = instance;
Ian Elliott1cb77a62015-12-29 16:44:39 -0700179 my_data->instanceMap[instance].surfaceExtensionEnabled = false;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600180
181 // Record whether the WSI instance extension was enabled for this
182 // VkInstance. No need to check if the extension was advertised by
183 // vkEnumerateInstanceExtensionProperties(), since the loader handles that.
Chia-I Wud50a7d72015-10-26 20:48:51 +0800184 for (i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Ian Elliott1dcd1092015-11-17 17:29:40 -0700185 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600186
Ian Elliott1cb77a62015-12-29 16:44:39 -0700187 my_data->instanceMap[instance].surfaceExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600188 }
189 }
190}
191
192
193#include "vk_dispatch_table_helper.h"
Courtney Goeltzenleuchter6d8e8182015-11-25 14:31:49 -0700194static void initSwapchain(layer_data *my_data, const VkAllocationCallbacks *pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600195{
196 uint32_t report_flags = 0;
197 uint32_t debug_action = 0;
198 FILE *log_output = NULL;
199 const char *option_str;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700200 VkDebugReportCallbackEXT callback;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600201
202 // Initialize Swapchain options:
203 report_flags = getLayerOptionFlags("SwapchainReportFlags", 0);
204 getLayerOptionEnum("SwapchainDebugAction", (uint32_t *) &debug_action);
205
206 if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)
207 {
208 // Turn on logging, since it was requested:
209 option_str = getLayerOption("SwapchainLogFilename");
210 log_output = getLayerLogOutput(option_str, "Swapchain");
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700211 VkDebugReportCallbackCreateInfoEXT dbgInfo;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700212 memset(&dbgInfo, 0, sizeof(dbgInfo));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700213 dbgInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700214 dbgInfo.pfnCallback = log_callback;
215 dbgInfo.pUserData = log_output;
216 dbgInfo.flags = report_flags;
217 layer_create_msg_callback(my_data->report_data,
218 &dbgInfo,
219 pAllocator,
Courtney Goeltzenleuchtercf60e0a2015-10-08 17:07:25 -0600220 &callback);
221 my_data->logging_callback.push_back(callback);
222 }
223 if (debug_action & VK_DBG_LAYER_ACTION_DEBUG_OUTPUT) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700224 VkDebugReportCallbackCreateInfoEXT dbgInfo;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700225 memset(&dbgInfo, 0, sizeof(dbgInfo));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700226 dbgInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700227 dbgInfo.pfnCallback = win32_debug_output_msg;
228 dbgInfo.pUserData = log_output;
229 dbgInfo.flags = report_flags;
230 layer_create_msg_callback(my_data->report_data, &dbgInfo, pAllocator, &callback);
Courtney Goeltzenleuchtercf60e0a2015-10-08 17:07:25 -0600231 my_data->logging_callback.push_back(callback);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600232 }
233}
234
Ian Elliott27d39c72015-11-20 16:39:34 -0700235static const char *surfaceTransformStr(VkSurfaceTransformFlagBitsKHR value)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600236{
Ian Elliott0b4d6242015-09-22 10:51:24 -0600237 // Return a string corresponding to the value:
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700238 return string_VkSurfaceTransformFlagBitsKHR(value);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600239}
240
Ian Elliotta2a89c52015-12-28 15:23:57 -0700241static const char *surfaceCompositeAlphaStr(VkCompositeAlphaFlagBitsKHR value)
242{
243 // Return a string corresponding to the value:
244 return string_VkCompositeAlphaFlagBitsKHR(value);
245}
246
Ian Elliott0b4d6242015-09-22 10:51:24 -0600247static const char *presentModeStr(VkPresentModeKHR value)
248{
Ian Elliott0b4d6242015-09-22 10:51:24 -0600249 // Return a string corresponding to the value:
Ian Elliott24491af2015-12-28 15:04:49 -0700250 return string_VkPresentModeKHR(value);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600251}
252
Ian Elliotta2a89c52015-12-28 15:23:57 -0700253static const char *sharingModeStr(VkSharingMode value)
254{
255 // Return a string corresponding to the value:
256 return string_VkSharingMode(value);
257}
258
Ian Elliott0b4d6242015-09-22 10:51:24 -0600259
Chia-I Wu9ab61502015-11-06 06:42:02 +0800260VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600261{
Tobin Ehlis711ff312015-10-29 12:58:13 -0600262 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600263 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600264 VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
Chia-I Wuf7458c52015-10-26 21:10:41 +0800265 VkResult result = pTable->CreateInstance(pCreateInfo, pAllocator, pInstance);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600266 if (result == VK_SUCCESS) {
267 // Since it succeeded, do layer-specific work:
Ian Elliott68124ac2015-10-07 16:18:35 -0600268 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
269 my_data->report_data = debug_report_create_instance(
Tobin Ehlis711ff312015-10-29 12:58:13 -0600270 pTable,
Ian Elliott68124ac2015-10-07 16:18:35 -0600271 *pInstance,
Chia-I Wud50a7d72015-10-26 20:48:51 +0800272 pCreateInfo->enabledExtensionNameCount,
Ian Elliott68124ac2015-10-07 16:18:35 -0600273 pCreateInfo->ppEnabledExtensionNames);
274 // Call the following function after my_data is initialized:
Ian Elliott0b4d6242015-09-22 10:51:24 -0600275 createInstanceRegisterExtensions(pCreateInfo, *pInstance);
Courtney Goeltzenleuchter6d8e8182015-11-25 14:31:49 -0700276 initSwapchain(my_data, pAllocator);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600277 }
278 return result;
279}
280
Chia-I Wu9ab61502015-11-06 06:42:02 +0800281VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600282{
283 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600284 dispatch_key key = get_dispatch_key(instance);
285 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600286 // Validate that a valid VkInstance was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600287 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600288 if (!pInstance) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700289 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600290 instance,
291 "VkInstance");
292 }
293
294 if (VK_FALSE == skipCall) {
295 // Call down the call chain:
Chia-I Wuf7458c52015-10-26 21:10:41 +0800296 my_data->instance_dispatch_table->DestroyInstance(instance, pAllocator);
Ian Elliott68124ac2015-10-07 16:18:35 -0600297
298 // Clean up logging callback, if any
Courtney Goeltzenleuchtercf60e0a2015-10-08 17:07:25 -0600299 while (my_data->logging_callback.size() > 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700300 VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700301 layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
Courtney Goeltzenleuchtercf60e0a2015-10-08 17:07:25 -0600302 my_data->logging_callback.pop_back();
Ian Elliott68124ac2015-10-07 16:18:35 -0600303 }
304 layer_debug_report_destroy_instance(my_data->report_data);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600305 }
306
307 // Regardless of skipCall value, do some internal cleanup:
308 if (pInstance) {
309 // Delete all of the SwpPhysicalDevice's and the SwpInstance associated
310 // with this instance:
311 for (auto it = pInstance->physicalDevices.begin() ;
312 it != pInstance->physicalDevices.end() ; it++) {
Ian Elliott27d39c72015-11-20 16:39:34 -0700313
314 // Free memory that was allocated for/by this SwpPhysicalDevice:
315 SwpPhysicalDevice *pPhysicalDevice = it->second;
316 free(pPhysicalDevice->pSurfaceFormats);
317 free(pPhysicalDevice->pPresentModes);
318
Tobin Ehlis711ff312015-10-29 12:58:13 -0600319 // Erase the SwpPhysicalDevice's from the my_data->physicalDeviceMap (which
Ian Elliott0b4d6242015-09-22 10:51:24 -0600320 // are simply pointed to by the SwpInstance):
Tobin Ehlis711ff312015-10-29 12:58:13 -0600321 my_data->physicalDeviceMap.erase(it->second->physicalDevice);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600322 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600323 my_data->instanceMap.erase(instance);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600324 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600325 delete my_data->instance_dispatch_table;
326 layer_data_map.erase(key);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600327}
328
Ian Elliotta983e9a2015-12-22 12:18:12 -0700329#ifdef VK_USE_PLATFORM_ANDROID_KHR
330VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR(
331 VkInstance instance,
Ian Elliott1bf155f2015-12-29 17:35:46 -0700332 const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
Ian Elliotta983e9a2015-12-22 12:18:12 -0700333 const VkAllocationCallbacks* pAllocator,
334 VkSurfaceKHR* pSurface)
335{
336 VkResult result = VK_SUCCESS;
337 VkBool32 skipCall = VK_FALSE;
338 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
339
340 // Validate that a valid VkInstance was used:
341 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
342 if (!pInstance) {
Ian Elliott1bf155f2015-12-29 17:35:46 -0700343 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliotta983e9a2015-12-22 12:18:12 -0700344 instance,
345 "VkInstance");
346 }
347
348 if (VK_FALSE == skipCall) {
349 // Call down the call chain:
350 result = my_data->instance_dispatch_table->CreateAndroidSurfaceKHR(
Ian Elliott1bf155f2015-12-29 17:35:46 -0700351 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliotta983e9a2015-12-22 12:18:12 -0700352
353 if ((result == VK_SUCCESS) && pInstance && pSurface) {
354 // Record the VkSurfaceKHR returned by the ICD:
355 my_data->surfaceMap[*pSurface].surface = *pSurface;
356 my_data->surfaceMap[*pSurface].pInstance = pInstance;
357 my_data->surfaceMap[*pSurface].platform = VK_ICD_WSI_PLATFORM_ANDROID;
358 // Point to the associated SwpInstance:
359 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
360 skipCall |= validateSurface(my_data, *pSurface, (char *) __FUNCTION__);
361 }
362 return result;
363 }
Ian Elliott1bf155f2015-12-29 17:35:46 -0700364 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliotta983e9a2015-12-22 12:18:12 -0700365}
366#endif // VK_USE_PLATFORM_ANDROID_KHR
367
368#ifdef VK_USE_PLATFORM_MIR_KHR
369VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMirSurfaceKHR(
370 VkInstance instance,
Ian Elliott1bf155f2015-12-29 17:35:46 -0700371 const VkMirSurfaceCreateInfoKHR* pCreateInfo,
Ian Elliotta983e9a2015-12-22 12:18:12 -0700372 const VkAllocationCallbacks* pAllocator,
373 VkSurfaceKHR* pSurface)
374{
375 VkResult result = VK_SUCCESS;
376 VkBool32 skipCall = VK_FALSE;
377 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
378
379 // Validate that a valid VkInstance was used:
380 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
381 if (!pInstance) {
Ian Elliott1bf155f2015-12-29 17:35:46 -0700382 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliotta983e9a2015-12-22 12:18:12 -0700383 instance,
384 "VkInstance");
385 }
386
387 if (VK_FALSE == skipCall) {
388 // Call down the call chain:
389 result = my_data->instance_dispatch_table->CreateMirSurfaceKHR(
Ian Elliott1bf155f2015-12-29 17:35:46 -0700390 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliotta983e9a2015-12-22 12:18:12 -0700391
392 if ((result == VK_SUCCESS) && pInstance && pSurface) {
393 // Record the VkSurfaceKHR returned by the ICD:
394 my_data->surfaceMap[*pSurface].surface = *pSurface;
395 my_data->surfaceMap[*pSurface].pInstance = pInstance;
396 my_data->surfaceMap[*pSurface].platform = VK_ICD_WSI_PLATFORM_MIR;
397 // Point to the associated SwpInstance:
398 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
399 skipCall |= validateSurface(my_data, *pSurface, (char *) __FUNCTION__);
400 }
401 return result;
402 }
Ian Elliott1bf155f2015-12-29 17:35:46 -0700403 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliotta983e9a2015-12-22 12:18:12 -0700404}
405#endif // VK_USE_PLATFORM_MIR_KHR
406
407#ifdef VK_USE_PLATFORM_WAYLAND_KHR
408VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR(
409 VkInstance instance,
Ian Elliott1bf155f2015-12-29 17:35:46 -0700410 const VkWaylandSurfaceCreateInfoKHR* pCreateInfo,
Ian Elliotta983e9a2015-12-22 12:18:12 -0700411 const VkAllocationCallbacks* pAllocator,
412 VkSurfaceKHR* pSurface)
413{
414 VkResult result = VK_SUCCESS;
415 VkBool32 skipCall = VK_FALSE;
416 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
417
418 // Validate that a valid VkInstance was used:
419 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
420 if (!pInstance) {
Ian Elliott1bf155f2015-12-29 17:35:46 -0700421 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliotta983e9a2015-12-22 12:18:12 -0700422 instance,
423 "VkInstance");
424 }
425
426 if (VK_FALSE == skipCall) {
427 // Call down the call chain:
428 result = my_data->instance_dispatch_table->CreateWaylandSurfaceKHR(
Ian Elliott1bf155f2015-12-29 17:35:46 -0700429 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliotta983e9a2015-12-22 12:18:12 -0700430
431 if ((result == VK_SUCCESS) && pInstance && pSurface) {
432 // Record the VkSurfaceKHR returned by the ICD:
433 my_data->surfaceMap[*pSurface].surface = *pSurface;
434 my_data->surfaceMap[*pSurface].pInstance = pInstance;
435 my_data->surfaceMap[*pSurface].platform = VK_ICD_WSI_PLATFORM_WAYLAND;
436 // Point to the associated SwpInstance:
437 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
438 skipCall |= validateSurface(my_data, *pSurface, (char *) __FUNCTION__);
439 }
440 return result;
441 }
Ian Elliott1bf155f2015-12-29 17:35:46 -0700442 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliotta983e9a2015-12-22 12:18:12 -0700443}
444#endif // VK_USE_PLATFORM_WAYLAND_KHR
445
446#ifdef VK_USE_PLATFORM_WIN32_KHR
447VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR(
448 VkInstance instance,
Ian Elliott1bf155f2015-12-29 17:35:46 -0700449 const VkWin32SurfaceCreateInfoKHR* pCreateInfo,
Ian Elliotta983e9a2015-12-22 12:18:12 -0700450 const VkAllocationCallbacks* pAllocator,
451 VkSurfaceKHR* pSurface)
452{
453 VkResult result = VK_SUCCESS;
454 VkBool32 skipCall = VK_FALSE;
455 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
456
457 // Validate that a valid VkInstance was used:
458 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
459 if (!pInstance) {
Ian Elliott1bf155f2015-12-29 17:35:46 -0700460 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliotta983e9a2015-12-22 12:18:12 -0700461 instance,
462 "VkInstance");
463 }
464
465 if (VK_FALSE == skipCall) {
466 // Call down the call chain:
467 result = my_data->instance_dispatch_table->CreateWin32SurfaceKHR(
Ian Elliott1bf155f2015-12-29 17:35:46 -0700468 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliotta983e9a2015-12-22 12:18:12 -0700469
470 if ((result == VK_SUCCESS) && pInstance && pSurface) {
471 // Record the VkSurfaceKHR returned by the ICD:
472 my_data->surfaceMap[*pSurface].surface = *pSurface;
473 my_data->surfaceMap[*pSurface].pInstance = pInstance;
474 my_data->surfaceMap[*pSurface].platform = VK_ICD_WSI_PLATFORM_WIN32;
475 // Point to the associated SwpInstance:
476 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
477 skipCall |= validateSurface(my_data, *pSurface, (char *) __FUNCTION__);
478 }
479 return result;
480 }
Ian Elliott1bf155f2015-12-29 17:35:46 -0700481 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliotta983e9a2015-12-22 12:18:12 -0700482}
483#endif // VK_USE_PLATFORM_WIN32_KHR
484
485#ifdef VK_USE_PLATFORM_XCB_KHR
486VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(
487 VkInstance instance,
Ian Elliott1bf155f2015-12-29 17:35:46 -0700488 const VkXcbSurfaceCreateInfoKHR* pCreateInfo,
Ian Elliotta983e9a2015-12-22 12:18:12 -0700489 const VkAllocationCallbacks* pAllocator,
490 VkSurfaceKHR* pSurface)
491{
492 VkResult result = VK_SUCCESS;
493 VkBool32 skipCall = VK_FALSE;
494 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
495
496 // Validate that a valid VkInstance was used:
497 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
498 if (!pInstance) {
Ian Elliott1bf155f2015-12-29 17:35:46 -0700499 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliotta983e9a2015-12-22 12:18:12 -0700500 instance,
501 "VkInstance");
502 }
503
504 if (VK_FALSE == skipCall) {
505 // Call down the call chain:
506 result = my_data->instance_dispatch_table->CreateXcbSurfaceKHR(
Ian Elliott1bf155f2015-12-29 17:35:46 -0700507 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliotta983e9a2015-12-22 12:18:12 -0700508
509 if ((result == VK_SUCCESS) && pInstance && pSurface) {
510 // Record the VkSurfaceKHR returned by the ICD:
511 my_data->surfaceMap[*pSurface].surface = *pSurface;
512 my_data->surfaceMap[*pSurface].pInstance = pInstance;
513 my_data->surfaceMap[*pSurface].platform = VK_ICD_WSI_PLATFORM_XCB;
514 // Point to the associated SwpInstance:
515 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
516 skipCall |= validateSurface(my_data, *pSurface, (char *) __FUNCTION__);
517 }
518 return result;
519 }
Ian Elliott1bf155f2015-12-29 17:35:46 -0700520 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliotta983e9a2015-12-22 12:18:12 -0700521}
522#endif // VK_USE_PLATFORM_XCB_KHR
523
524#ifdef VK_USE_PLATFORM_XLIB_KHR
525VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(
526 VkInstance instance,
Ian Elliott1bf155f2015-12-29 17:35:46 -0700527 const VkXlibSurfaceCreateInfoKHR* pCreateInfo,
Ian Elliotta983e9a2015-12-22 12:18:12 -0700528 const VkAllocationCallbacks* pAllocator,
529 VkSurfaceKHR* pSurface)
530{
531 VkResult result = VK_SUCCESS;
532 VkBool32 skipCall = VK_FALSE;
533 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
534
535 // Validate that a valid VkInstance was used:
536 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
537 if (!pInstance) {
Ian Elliott1bf155f2015-12-29 17:35:46 -0700538 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliotta983e9a2015-12-22 12:18:12 -0700539 instance,
540 "VkInstance");
541 }
542
543 if (VK_FALSE == skipCall) {
544 // Call down the call chain:
545 result = my_data->instance_dispatch_table->CreateXlibSurfaceKHR(
Ian Elliott1bf155f2015-12-29 17:35:46 -0700546 instance, pCreateInfo, pAllocator, pSurface);
Ian Elliotta983e9a2015-12-22 12:18:12 -0700547
548 if ((result == VK_SUCCESS) && pInstance && pSurface) {
549 // Record the VkSurfaceKHR returned by the ICD:
550 my_data->surfaceMap[*pSurface].surface = *pSurface;
551 my_data->surfaceMap[*pSurface].pInstance = pInstance;
552 my_data->surfaceMap[*pSurface].platform = VK_ICD_WSI_PLATFORM_XLIB;
553 // Point to the associated SwpInstance:
554 pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
555 skipCall |= validateSurface(my_data, *pSurface, (char *) __FUNCTION__);
556 }
557 return result;
558 }
Ian Elliott1bf155f2015-12-29 17:35:46 -0700559 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliotta983e9a2015-12-22 12:18:12 -0700560}
561#endif // VK_USE_PLATFORM_XLIB_KHR
562
563VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator)
564{
565 VkBool32 skipCall = VK_FALSE;
566 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
567
568 // Validate that a valid VkInstance was used:
569 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
570 if (!pInstance) {
Ian Elliott1bf155f2015-12-29 17:35:46 -0700571 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliotta983e9a2015-12-22 12:18:12 -0700572 instance,
573 "VkInstance");
574 }
575
576 if (VK_FALSE == skipCall) {
577 // Validate that a valid VkSurfaceKHR was used:
578 skipCall |= validateSurface(my_data, surface, (char *) __FUNCTION__);
579 }
580
581 if (VK_FALSE == skipCall) {
582 // Call down the call chain:
583 my_data->instance_dispatch_table->DestroySurfaceKHR(
584 instance, surface, pAllocator);
585 }
586
587 // Regardless of skipCall value, do some internal cleanup:
588 SwpSurface *pSurface = &my_data->surfaceMap[surface];
589 if (pSurface && pSurface->pInstance) {
590 pSurface->pInstance->surfaces.erase(surface);
591 }
592 my_data->surfaceMap.erase(surface);
593}
594
Chia-I Wu9ab61502015-11-06 06:42:02 +0800595VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600596{
597 VkResult result = VK_SUCCESS;
598 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600599 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600600
601 // Validate that a valid VkInstance was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600602 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600603 if (!pInstance) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700604 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600605 instance,
606 "VkInstance");
607 }
608
609 if (VK_FALSE == skipCall) {
610 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600611 result = my_data->instance_dispatch_table->EnumeratePhysicalDevices(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600612 instance, pPhysicalDeviceCount, pPhysicalDevices);
613
614 if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices &&
615 (*pPhysicalDeviceCount > 0)) {
616 // Record the VkPhysicalDevices returned by the ICD:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600617 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600618 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
Tobin Ehlis711ff312015-10-29 12:58:13 -0600619 my_data->physicalDeviceMap[pPhysicalDevices[i]].physicalDevice =
Ian Elliott0b4d6242015-09-22 10:51:24 -0600620 pPhysicalDevices[i];
Tobin Ehlis711ff312015-10-29 12:58:13 -0600621 my_data->physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance;
622 my_data->physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL;
Ian Elliott27d39c72015-11-20 16:39:34 -0700623 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotSurfaceCapabilities = false;
624 my_data->physicalDeviceMap[pPhysicalDevices[i]].surfaceFormatCount = 0;
625 my_data->physicalDeviceMap[pPhysicalDevices[i]].pSurfaceFormats = NULL;
626 my_data->physicalDeviceMap[pPhysicalDevices[i]].presentModeCount = 0;
627 my_data->physicalDeviceMap[pPhysicalDevices[i]].pPresentModes = NULL;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600628 // Point to the associated SwpInstance:
629 pInstance->physicalDevices[pPhysicalDevices[i]] =
Tobin Ehlis711ff312015-10-29 12:58:13 -0600630 &my_data->physicalDeviceMap[pPhysicalDevices[i]];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600631 }
632 }
633
634 return result;
635 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700636 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600637}
638
Chia-I Wu9ab61502015-11-06 06:42:02 +0800639VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600640{
641 VkResult result = VK_SUCCESS;
642 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600643 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600644
645 // Validate that a valid VkPhysicalDevice was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600646 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600647 if (!pPhysicalDevice) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700648 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
Mark Lobodzinski6c1cb5a2015-11-05 15:27:03 -0700649 physicalDevice, "VkPhysicalDevice");
Ian Elliott0b4d6242015-09-22 10:51:24 -0600650 }
651
Tobin Ehlis711ff312015-10-29 12:58:13 -0600652 if (VK_TRUE == skipCall)
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700653 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600654
655 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
656 // Call down the call chain:
657 result = my_device_data->device_dispatch_table->CreateDevice(
Chia-I Wuf7458c52015-10-26 21:10:41 +0800658 physicalDevice, pCreateInfo, pAllocator, pDevice);
Tobin Ehlis711ff312015-10-29 12:58:13 -0600659 if (result == VK_SUCCESS) {
660 // Since it succeeded, do layer-specific work:
Mark Lobodzinski6c1cb5a2015-11-05 15:27:03 -0700661 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
662 my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
663 createDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600664 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600665 return result;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600666}
667
Chia-I Wu9ab61502015-11-06 06:42:02 +0800668VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600669{
670 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600671 dispatch_key key = get_dispatch_key(device);
672 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600673 // Validate that a valid VkDevice was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600674 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600675 if (!pDevice) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700676 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600677 device,
678 "VkDevice");
679 }
680
681 if (VK_FALSE == skipCall) {
682 // Call down the call chain:
Chia-I Wuf7458c52015-10-26 21:10:41 +0800683 my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600684 }
685
686 // Regardless of skipCall value, do some internal cleanup:
687 if (pDevice) {
688 // Delete the SwpDevice associated with this device:
689 if (pDevice->pPhysicalDevice) {
690 pDevice->pPhysicalDevice->pDevice = NULL;
691 }
Ian Elliott0b4d6242015-09-22 10:51:24 -0600692 if (!pDevice->swapchains.empty()) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700693 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600694 SWAPCHAIN_DEL_DEVICE_BEFORE_SWAPCHAINS,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600695 "%s() called before all of its associated "
696 "VkSwapchainKHRs were destroyed.",
697 __FUNCTION__);
698 // Empty and then delete all SwpSwapchain's
699 for (auto it = pDevice->swapchains.begin() ;
700 it != pDevice->swapchains.end() ; it++) {
701 // Delete all SwpImage's
702 it->second->images.clear();
703 }
704 pDevice->swapchains.clear();
705 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600706 my_data->deviceMap.erase(device);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600707 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600708 delete my_data->device_dispatch_table;
709 layer_data_map.erase(key);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600710}
711
Ian Elliott27d39c72015-11-20 16:39:34 -0700712VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(
713 VkPhysicalDevice physicalDevice,
714 uint32_t queueFamilyIndex,
715 VkSurfaceKHR surface,
716 VkBool32* pSupported)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600717{
718 VkResult result = VK_SUCCESS;
719 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600720 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600721
722 // Validate that a valid VkPhysicalDevice was used, and that the instance
723 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600724 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600725 if (!pPhysicalDevice || !pPhysicalDevice->pInstance) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700726 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600727 physicalDevice,
728 "VkPhysicalDevice");
Ian Elliott1cb77a62015-12-29 16:44:39 -0700729 } else if (!pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700730 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600731 pPhysicalDevice->pInstance,
732 "VkInstance",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600733 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800734 "%s() called even though the %s extension was not enabled for this VkInstance.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700735 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600736 }
Ian Elliotta983e9a2015-12-22 12:18:12 -0700737 skipCall |= validateSurface(my_data, surface, (char *) __FUNCTION__);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600738
739 if (VK_FALSE == skipCall) {
740 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600741 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(
Ian Elliott27d39c72015-11-20 16:39:34 -0700742 physicalDevice, queueFamilyIndex, surface,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600743 pSupported);
744
745 if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
746 // Record the result of this query:
747 pPhysicalDevice->queueFamilyIndexSupport[queueFamilyIndex] =
748 *pSupported;
749 // TODO: We need to compare this with the actual queue used for
750 // presentation, to ensure it was advertised to the application as
751 // supported for presentation.
752 }
753
754 return result;
755 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700756 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600757}
758
Ian Elliott27d39c72015-11-20 16:39:34 -0700759VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
760 VkPhysicalDevice physicalDevice,
761 VkSurfaceKHR surface,
762 VkSurfaceCapabilitiesKHR* pSurfaceCapabilities)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600763{
764 VkResult result = VK_SUCCESS;
765 VkBool32 skipCall = VK_FALSE;
Ian Elliott27d39c72015-11-20 16:39:34 -0700766 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600767
Ian Elliott27d39c72015-11-20 16:39:34 -0700768 // Validate that a valid VkPhysicalDevice was used, and that the instance
Ian Elliott0b4d6242015-09-22 10:51:24 -0600769 // extension was enabled:
Ian Elliott27d39c72015-11-20 16:39:34 -0700770 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
771 if (!pPhysicalDevice || !pPhysicalDevice->pInstance) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700772 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -0700773 physicalDevice,
774 "VkPhysicalDevice");
Ian Elliott1cb77a62015-12-29 16:44:39 -0700775 } else if (!pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700776 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -0700777 pPhysicalDevice->pInstance,
778 "VkInstance",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600779 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott27d39c72015-11-20 16:39:34 -0700780 "%s() called even though the %s extension was not enabled for this VkInstance.",
781 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600782 }
Ian Elliotta983e9a2015-12-22 12:18:12 -0700783 skipCall |= validateSurface(my_data, surface, (char *) __FUNCTION__);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600784
785 if (VK_FALSE == skipCall) {
786 // Call down the call chain:
Ian Elliott27d39c72015-11-20 16:39:34 -0700787 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceCapabilitiesKHR(
788 physicalDevice, surface, pSurfaceCapabilities);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600789
Ian Elliott27d39c72015-11-20 16:39:34 -0700790 if ((result == VK_SUCCESS) && pPhysicalDevice) {
791 pPhysicalDevice->gotSurfaceCapabilities = true;
792// FIXME: NEED TO COPY THIS DATA, BECAUSE pSurfaceCapabilities POINTS TO APP-ALLOCATED DATA
793 pPhysicalDevice->surfaceCapabilities = *pSurfaceCapabilities;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600794 }
795
796 return result;
797 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700798 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600799}
800
Ian Elliott27d39c72015-11-20 16:39:34 -0700801VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR(
802 VkPhysicalDevice physicalDevice,
803 VkSurfaceKHR surface,
804 uint32_t* pCount,
805 VkSurfaceFormatKHR* pSurfaceFormats)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600806{
807 VkResult result = VK_SUCCESS;
808 VkBool32 skipCall = VK_FALSE;
Ian Elliott27d39c72015-11-20 16:39:34 -0700809 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600810
Ian Elliott27d39c72015-11-20 16:39:34 -0700811 // Validate that a valid VkPhysicalDevice was used, and that the instance
Ian Elliott0b4d6242015-09-22 10:51:24 -0600812 // extension was enabled:
Ian Elliott27d39c72015-11-20 16:39:34 -0700813 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
814 if (!pPhysicalDevice || !pPhysicalDevice->pInstance) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700815 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -0700816 physicalDevice,
817 "VkPhysicalDevice");
Ian Elliott1cb77a62015-12-29 16:44:39 -0700818 } else if (!pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700819 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -0700820 pPhysicalDevice->pInstance,
821 "VkInstance",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600822 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott27d39c72015-11-20 16:39:34 -0700823 "%s() called even though the %s extension was not enabled for this VkInstance.",
824 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600825 }
Ian Elliotta983e9a2015-12-22 12:18:12 -0700826 skipCall |= validateSurface(my_data, surface, (char *) __FUNCTION__);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600827
828 if (VK_FALSE == skipCall) {
829 // Call down the call chain:
Ian Elliott27d39c72015-11-20 16:39:34 -0700830 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceFormatsKHR(
831 physicalDevice, surface, pCount, pSurfaceFormats);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600832
Ian Elliott27d39c72015-11-20 16:39:34 -0700833 if ((result == VK_SUCCESS) && pPhysicalDevice && pSurfaceFormats && pCount &&
Ian Elliott0b4d6242015-09-22 10:51:24 -0600834 (*pCount > 0)) {
Ian Elliott27d39c72015-11-20 16:39:34 -0700835 pPhysicalDevice->surfaceFormatCount = *pCount;
836 pPhysicalDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600837 malloc(*pCount * sizeof(VkSurfaceFormatKHR));
Ian Elliott27d39c72015-11-20 16:39:34 -0700838 if (pPhysicalDevice->pSurfaceFormats) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600839 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott27d39c72015-11-20 16:39:34 -0700840 pPhysicalDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600841 }
842 } else {
Ian Elliott27d39c72015-11-20 16:39:34 -0700843 pPhysicalDevice->surfaceFormatCount = 0;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600844 }
845 }
846
847 return result;
848 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700849 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600850}
851
Ian Elliott27d39c72015-11-20 16:39:34 -0700852VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR(
853 VkPhysicalDevice physicalDevice,
854 VkSurfaceKHR surface,
855 uint32_t* pCount,
856 VkPresentModeKHR* pPresentModes)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600857{
858 VkResult result = VK_SUCCESS;
859 VkBool32 skipCall = VK_FALSE;
Ian Elliott27d39c72015-11-20 16:39:34 -0700860 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600861
Ian Elliott27d39c72015-11-20 16:39:34 -0700862 // Validate that a valid VkPhysicalDevice was used, and that the instance
Ian Elliott0b4d6242015-09-22 10:51:24 -0600863 // extension was enabled:
Ian Elliott27d39c72015-11-20 16:39:34 -0700864 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
865 if (!pPhysicalDevice || !pPhysicalDevice->pInstance) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700866 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -0700867 physicalDevice,
868 "VkPhysicalDevice");
Ian Elliott1cb77a62015-12-29 16:44:39 -0700869 } else if (!pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700870 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -0700871 pPhysicalDevice->pInstance,
872 "VkInstance",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600873 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott27d39c72015-11-20 16:39:34 -0700874 "%s() called even though the %s extension was not enabled for this VkInstance.",
875 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600876 }
Ian Elliotta983e9a2015-12-22 12:18:12 -0700877 skipCall |= validateSurface(my_data, surface, (char *) __FUNCTION__);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600878
879 if (VK_FALSE == skipCall) {
880 // Call down the call chain:
Ian Elliott27d39c72015-11-20 16:39:34 -0700881 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfacePresentModesKHR(
882 physicalDevice, surface, pCount, pPresentModes);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600883
Ian Elliott27d39c72015-11-20 16:39:34 -0700884 if ((result == VK_SUCCESS) && pPhysicalDevice && pPresentModes && pCount &&
Ian Elliott0b4d6242015-09-22 10:51:24 -0600885 (*pCount > 0)) {
Ian Elliott27d39c72015-11-20 16:39:34 -0700886 pPhysicalDevice->presentModeCount = *pCount;
887 pPhysicalDevice->pPresentModes = (VkPresentModeKHR *)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600888 malloc(*pCount * sizeof(VkPresentModeKHR));
Ian Elliott27d39c72015-11-20 16:39:34 -0700889 if (pPhysicalDevice->pSurfaceFormats) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600890 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott27d39c72015-11-20 16:39:34 -0700891 pPhysicalDevice->pPresentModes[i] = pPresentModes[i];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600892 }
893 } else {
Ian Elliott27d39c72015-11-20 16:39:34 -0700894 pPhysicalDevice->presentModeCount = 0;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600895 }
896 }
897
898 return result;
899 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700900 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600901}
902
903// This function does the up-front validation work for vkCreateSwapchainKHR(),
904// and returns VK_TRUE if a logging callback indicates that the call down the
905// chain should be skipped:
906static VkBool32 validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, VkSwapchainKHR* pSwapchain)
907{
908// TODO: Validate cases of re-creating a swapchain (the current code
909// assumes a new swapchain is being created).
910 VkResult result = VK_SUCCESS;
911 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600912 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600913 char fn[] = "vkCreateSwapchainKHR";
914
915 // Validate that a valid VkDevice was used, and that the device
916 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600917 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600918 if (!pDevice) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700919 return LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600920 SWAPCHAIN_INVALID_HANDLE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600921 "%s() called with a non-valid %s.",
922 fn, "VkDevice");
923
Ian Elliott427058f2015-12-29 16:45:49 -0700924 } else if (!pDevice->swapchainExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700925 return LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600926 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800927 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700928 fn, VK_KHR_SWAPCHAIN_EXTENSION_NAME );
Ian Elliott0b4d6242015-09-22 10:51:24 -0600929 }
930
931 // Validate pCreateInfo with the results for previous queries:
Ian Elliott27d39c72015-11-20 16:39:34 -0700932 if (!pDevice->pPhysicalDevice && !pDevice->pPhysicalDevice->gotSurfaceCapabilities) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700933 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600934 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600935 "%s() called before calling "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700936 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
Ian Elliott0b4d6242015-09-22 10:51:24 -0600937 fn);
938 } else {
Ian Elliotta983e9a2015-12-22 12:18:12 -0700939 // Validate pCreateInfo->surface, to ensure it is valid (Note: in order
940 // to validate, we must lookup layer_data based on the VkInstance
941 // associated with this VkDevice):
942 SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
943 SwpInstance *pInstance = pPhysicalDevice->pInstance;
944 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(pInstance->instance), layer_data_map);
945 skipCall |= validateSurface(my_instance_data,
946 pCreateInfo->surface,
947 (char *) "vkCreateSwapchainKHR");
Ian Elliott0b4d6242015-09-22 10:51:24 -0600948 // Validate pCreateInfo->minImageCount against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700949 // VkSurfaceCapabilitiesKHR::{min|max}ImageCount:
Ian Elliott27d39c72015-11-20 16:39:34 -0700950 VkSurfaceCapabilitiesKHR *pCapabilities = &pDevice->pPhysicalDevice->surfaceCapabilities;
951 if ((pCreateInfo->minImageCount < pCapabilities->minImageCount) ||
952 ((pCapabilities->maxImageCount > 0) &&
953 (pCreateInfo->minImageCount > pCapabilities->maxImageCount))) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700954 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600955 SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600956 "%s() called with pCreateInfo->minImageCount "
957 "= %d, which is outside the bounds returned "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700958 "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. "
Ian Elliott0b4d6242015-09-22 10:51:24 -0600959 "minImageCount = %d, maxImageCount = %d).",
960 fn,
961 pCreateInfo->minImageCount,
Ian Elliott27d39c72015-11-20 16:39:34 -0700962 pCapabilities->minImageCount,
963 pCapabilities->maxImageCount);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600964 }
965 // Validate pCreateInfo->imageExtent against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700966 // VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
Ian Elliott27d39c72015-11-20 16:39:34 -0700967 if ((pCapabilities->currentExtent.width == -1) &&
968 ((pCreateInfo->imageExtent.width < pCapabilities->minImageExtent.width) ||
969 (pCreateInfo->imageExtent.width > pCapabilities->maxImageExtent.width) ||
970 (pCreateInfo->imageExtent.height < pCapabilities->minImageExtent.height) ||
971 (pCreateInfo->imageExtent.height > pCapabilities->maxImageExtent.height))) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700972 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600973 SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600974 "%s() called with pCreateInfo->imageExtent = "
975 "(%d,%d), which is outside the bounds "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700976 "returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): "
Ian Elliott0b4d6242015-09-22 10:51:24 -0600977 "currentExtent = (%d,%d), minImageExtent = "
978 "(%d,%d), maxImageExtent = (%d,%d).",
979 fn,
980 pCreateInfo->imageExtent.width,
981 pCreateInfo->imageExtent.height,
Ian Elliott27d39c72015-11-20 16:39:34 -0700982 pCapabilities->currentExtent.width,
983 pCapabilities->currentExtent.height,
984 pCapabilities->minImageExtent.width,
985 pCapabilities->minImageExtent.height,
986 pCapabilities->maxImageExtent.width,
987 pCapabilities->maxImageExtent.height);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600988 }
Ian Elliott27d39c72015-11-20 16:39:34 -0700989 if ((pCapabilities->currentExtent.width != -1) &&
990 ((pCreateInfo->imageExtent.width != pCapabilities->currentExtent.width) ||
991 (pCreateInfo->imageExtent.height != pCapabilities->currentExtent.height))) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700992 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600993 SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600994 "%s() called with pCreateInfo->imageExtent = "
995 "(%d,%d), which is not equal to the "
996 "currentExtent = (%d,%d) returned by "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700997 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
Ian Elliott0b4d6242015-09-22 10:51:24 -0600998 fn,
999 pCreateInfo->imageExtent.width,
1000 pCreateInfo->imageExtent.height,
Ian Elliott27d39c72015-11-20 16:39:34 -07001001 pCapabilities->currentExtent.width,
1002 pCapabilities->currentExtent.height);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001003 }
1004 // Validate pCreateInfo->preTransform against
Ian Elliott1dcd1092015-11-17 17:29:40 -07001005 // VkSurfaceCapabilitiesKHR::supportedTransforms:
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -07001006 if (!((pCreateInfo->preTransform) & pCapabilities->supportedTransforms)) {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001007 // This is an error situation; one for which we'd like to give
1008 // the developer a helpful, multi-line error message. Build it
1009 // up a little at a time, and then log it:
1010 std::string errorString = "";
1011 char str[1024];
1012 // Here's the first part of the message:
1013 sprintf(str, "%s() called with a non-supported "
1014 "pCreateInfo->preTransform (i.e. %s). "
1015 "Supported values are:\n",
1016 fn,
1017 surfaceTransformStr(pCreateInfo->preTransform));
1018 errorString += str;
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -07001019 for (int i = 0; i < 32; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001020 // Build up the rest of the message:
Ian Elliott27d39c72015-11-20 16:39:34 -07001021 if ((1 << i) & pCapabilities->supportedTransforms) {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001022 const char *newStr =
Ian Elliott27d39c72015-11-20 16:39:34 -07001023 surfaceTransformStr((VkSurfaceTransformFlagBitsKHR) (1 << i));
Ian Elliott0b4d6242015-09-22 10:51:24 -06001024 sprintf(str, " %s\n", newStr);
1025 errorString += str;
1026 }
1027 }
1028 // Log the message that we've built up:
Ian Elliott68124ac2015-10-07 16:18:35 -06001029 skipCall |= debug_report_log_msg(my_data->report_data,
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001030 VK_DEBUG_REPORT_ERROR_BIT_EXT,
1031 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
Mark Lobodzinski80e774f2016-01-04 15:54:59 -07001032 (uint64_t) device, __LINE__,
Ian Elliottb0f474c2015-09-25 15:50:55 -06001033 SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM,
1034 LAYER_NAME,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001035 errorString.c_str());
1036 }
Ian Elliotta2a89c52015-12-28 15:23:57 -07001037 // Validate pCreateInfo->compositeAlpha against
1038 // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha:
1039 if (!((pCreateInfo->compositeAlpha) & pCapabilities->supportedCompositeAlpha)) {
1040 // This is an error situation; one for which we'd like to give
1041 // the developer a helpful, multi-line error message. Build it
1042 // up a little at a time, and then log it:
1043 std::string errorString = "";
1044 char str[1024];
1045 // Here's the first part of the message:
1046 sprintf(str, "%s() called with a non-supported "
1047 "pCreateInfo->compositeAlpha (i.e. %s). "
1048 "Supported values are:\n",
1049 fn,
1050 surfaceCompositeAlphaStr(pCreateInfo->compositeAlpha));
1051 errorString += str;
1052 for (int i = 0; i < 32; i++) {
1053 // Build up the rest of the message:
1054 if ((1 << i) & pCapabilities->supportedCompositeAlpha) {
1055 const char *newStr =
1056 surfaceCompositeAlphaStr((VkCompositeAlphaFlagBitsKHR) (1 << i));
1057 sprintf(str, " %s\n", newStr);
1058 errorString += str;
1059 }
1060 }
1061 // Log the message that we've built up:
1062 skipCall |= debug_report_log_msg(my_data->report_data,
Ian Elliott1bf155f2015-12-29 17:35:46 -07001063 VK_DEBUG_REPORT_ERROR_BIT_EXT,
1064 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
Ian Elliotta2a89c52015-12-28 15:23:57 -07001065 (uint64_t) device, 0,
1066 SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA,
1067 LAYER_NAME,
1068 errorString.c_str());
1069 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001070 // Validate pCreateInfo->imageArraySize against
Ian Elliott1dcd1092015-11-17 17:29:40 -07001071 // VkSurfaceCapabilitiesKHR::maxImageArraySize:
Mark Lobodzinskia3b44522015-12-11 11:05:33 -07001072 if (pCreateInfo->imageArrayLayers > pCapabilities->maxImageArrayLayers) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001073 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001074 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_SIZE,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001075 "%s() called with a non-supported "
1076 "pCreateInfo->imageArraySize (i.e. %d). "
1077 "Maximum value is %d.",
1078 fn,
Ian Elliott27d39c72015-11-20 16:39:34 -07001079 pCreateInfo->imageArrayLayers,
1080 pCapabilities->maxImageArrayLayers);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001081 }
Ian Elliott27d39c72015-11-20 16:39:34 -07001082 // Validate pCreateInfo->imageUsage against
Ian Elliott1dcd1092015-11-17 17:29:40 -07001083 // VkSurfaceCapabilitiesKHR::supportedUsageFlags:
Ian Elliott27d39c72015-11-20 16:39:34 -07001084 if (pCreateInfo->imageUsage &&
1085 (pCreateInfo->imageUsage !=
1086 (pCreateInfo->imageUsage & pCapabilities->supportedUsageFlags))) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001087 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001088 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001089 "%s() called with a non-supported "
Ian Elliott27d39c72015-11-20 16:39:34 -07001090 "pCreateInfo->imageUsage (i.e. 0x%08x)."
Ian Elliott0b4d6242015-09-22 10:51:24 -06001091 " Supported flag bits are 0x%08x.",
1092 fn,
Ian Elliott27d39c72015-11-20 16:39:34 -07001093 pCreateInfo->imageUsage,
1094 pCapabilities->supportedUsageFlags);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001095 }
1096 }
Ian Elliott27d39c72015-11-20 16:39:34 -07001097 if (!pDevice->pPhysicalDevice && !pDevice->pPhysicalDevice->surfaceFormatCount) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001098 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001099 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001100 "%s() called before calling "
Ian Elliott1dcd1092015-11-17 17:29:40 -07001101 "vkGetPhysicalDeviceSurfaceFormatsKHR().",
Ian Elliott0b4d6242015-09-22 10:51:24 -06001102 fn);
1103 } else {
1104 // Validate pCreateInfo->imageFormat against
1105 // VkSurfaceFormatKHR::format:
1106 bool foundFormat = false;
1107 bool foundColorSpace = false;
1108 bool foundMatch = false;
Ian Elliott27d39c72015-11-20 16:39:34 -07001109 for (uint32_t i = 0 ; i < pDevice->pPhysicalDevice->surfaceFormatCount ; i++) {
1110 if (pCreateInfo->imageFormat == pDevice->pPhysicalDevice->pSurfaceFormats[i].format) {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001111 // Validate pCreateInfo->imageColorSpace against
1112 // VkSurfaceFormatKHR::colorSpace:
1113 foundFormat = true;
Ian Elliott27d39c72015-11-20 16:39:34 -07001114 if (pCreateInfo->imageColorSpace == pDevice->pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001115 foundMatch = true;
1116 break;
1117 }
1118 } else {
Ian Elliott27d39c72015-11-20 16:39:34 -07001119 if (pCreateInfo->imageColorSpace == pDevice->pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001120 foundColorSpace = true;
1121 }
1122 }
1123 }
1124 if (!foundMatch) {
1125 if (!foundFormat) {
1126 if (!foundColorSpace) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001127 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001128 "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001129 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001130 "%s() called with neither a "
1131 "supported pCreateInfo->imageFormat "
1132 "(i.e. %d) nor a supported "
1133 "pCreateInfo->imageColorSpace "
1134 "(i.e. %d).",
1135 fn,
1136 pCreateInfo->imageFormat,
1137 pCreateInfo->imageColorSpace);
1138 } else {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001139 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device,
Ian Elliottb0f474c2015-09-25 15:50:55 -06001140 "VkDevice",
1141 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001142 "%s() called with a non-supported "
1143 "pCreateInfo->imageFormat (i.e. %d).",
1144 fn, pCreateInfo->imageFormat);
1145 }
1146 } else if (!foundColorSpace) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001147 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001148 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001149 "%s() called with a non-supported "
1150 "pCreateInfo->imageColorSpace (i.e. %d).",
1151 fn, pCreateInfo->imageColorSpace);
1152 }
1153 }
1154 }
Ian Elliott27d39c72015-11-20 16:39:34 -07001155 if (!pDevice->pPhysicalDevice && !pDevice->pPhysicalDevice->presentModeCount) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001156 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001157 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001158 "%s() called before calling "
Ian Elliott1dcd1092015-11-17 17:29:40 -07001159 "vkGetPhysicalDeviceSurfacePresentModesKHR().",
Ian Elliott0b4d6242015-09-22 10:51:24 -06001160 fn);
1161 } else {
1162 // Validate pCreateInfo->presentMode against
Ian Elliott1dcd1092015-11-17 17:29:40 -07001163 // vkGetPhysicalDeviceSurfacePresentModesKHR():
Ian Elliott0b4d6242015-09-22 10:51:24 -06001164 bool foundMatch = false;
Ian Elliott27d39c72015-11-20 16:39:34 -07001165 for (uint32_t i = 0 ; i < pDevice->pPhysicalDevice->presentModeCount ; i++) {
1166 if (pDevice->pPhysicalDevice->pPresentModes[i] == pCreateInfo->presentMode) {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001167 foundMatch = true;
1168 break;
1169 }
1170 }
1171 if (!foundMatch) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001172 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001173 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001174 "%s() called with a non-supported "
1175 "pCreateInfo->presentMode (i.e. %s).",
1176 fn,
1177 presentModeStr(pCreateInfo->presentMode));
1178 }
1179 }
1180
Ian Elliotta2a89c52015-12-28 15:23:57 -07001181 if (pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT) {
1182 if ((pCreateInfo->queueFamilyIndexCount <= 1) ||
1183 !pCreateInfo->pQueueFamilyIndices) {
Ian Elliott1bf155f2015-12-29 17:35:46 -07001184 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliotta2a89c52015-12-28 15:23:57 -07001185 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_VALUES,
1186 "%s() called with a supported "
1187 "pCreateInfo->sharingMode of (i.e. %s),"
1188 "but with a bad value(s) for "
1189 "pCreateInfo->queueFamilyIndexCount or "
1190 "pCreateInfo->pQueueFamilyIndices).",
1191 fn,
1192 sharingModeStr(pCreateInfo->imageSharingMode));
1193 }
1194 } else if (pCreateInfo->imageSharingMode != VK_SHARING_MODE_EXCLUSIVE) {
Ian Elliott1bf155f2015-12-29 17:35:46 -07001195 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliotta2a89c52015-12-28 15:23:57 -07001196 SWAPCHAIN_CREATE_SWAP_BAD_SHARING_MODE,
1197 "%s() called with a non-supported "
1198 "pCreateInfo->imageSharingMode (i.e. %s).",
1199 fn,
1200 sharingModeStr(pCreateInfo->imageSharingMode));
1201 }
1202
1203 if ((pCreateInfo->clipped != VK_FALSE) &&
1204 (pCreateInfo->clipped != VK_TRUE)) {
Ian Elliott1bf155f2015-12-29 17:35:46 -07001205 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliotta2a89c52015-12-28 15:23:57 -07001206 SWAPCHAIN_BAD_BOOL,
1207 "%s() called with a VkBool32 value that is neither "
1208 "VK_TRUE nor VK_FALSE, but has the numeric value of %d.",
1209 fn,
1210 pCreateInfo->clipped);
1211 }
1212
1213 if (pCreateInfo->oldSwapchain) {
1214 SwpSwapchain *pSwapchain = &my_data->swapchainMap[pCreateInfo->oldSwapchain];
1215 if (pSwapchain) {
1216 if (device != pSwapchain->pDevice->device) {
Ian Elliott1bf155f2015-12-29 17:35:46 -07001217 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliotta2a89c52015-12-28 15:23:57 -07001218 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
1219 "%s() called with a different VkDevice than the "
1220 "VkSwapchainKHR was created with.",
1221 __FUNCTION__);
1222 }
1223 } else {
Ian Elliott1bf155f2015-12-29 17:35:46 -07001224 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
Ian Elliotta2a89c52015-12-28 15:23:57 -07001225 pCreateInfo->oldSwapchain,
1226 "VkSwapchainKHR");
1227 }
1228 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001229
1230 return skipCall;
1231}
1232
Ian Elliott27d39c72015-11-20 16:39:34 -07001233VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(
1234 VkDevice device,
1235 const VkSwapchainCreateInfoKHR* pCreateInfo,
1236 const VkAllocationCallbacks* pAllocator,
1237 VkSwapchainKHR* pSwapchain)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001238{
1239 VkResult result = VK_SUCCESS;
Tobin Ehlis711ff312015-10-29 12:58:13 -06001240 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001241 VkBool32 skipCall = validateCreateSwapchainKHR(device, pCreateInfo,
1242 pSwapchain);
1243
1244 if (VK_FALSE == skipCall) {
1245 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -06001246 result = my_data->device_dispatch_table->CreateSwapchainKHR(
Ian Elliott27d39c72015-11-20 16:39:34 -07001247 device, pCreateInfo, pAllocator, pSwapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001248
1249 if (result == VK_SUCCESS) {
1250 // Remember the swapchain's handle, and link it to the device:
Tobin Ehlis711ff312015-10-29 12:58:13 -06001251 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001252
Tobin Ehlis711ff312015-10-29 12:58:13 -06001253 my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
Chia-I Wue2fc5522015-10-26 20:04:44 +08001254 pDevice->swapchains[*pSwapchain] =
Tobin Ehlis711ff312015-10-29 12:58:13 -06001255 &my_data->swapchainMap[*pSwapchain];
1256 my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
1257 my_data->swapchainMap[*pSwapchain].imageCount = 0;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001258 }
1259
1260 return result;
1261 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07001262 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001263}
1264
Ian Elliott27d39c72015-11-20 16:39:34 -07001265VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR(
1266 VkDevice device,
1267 VkSwapchainKHR swapchain,
1268 const VkAllocationCallbacks* pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001269{
1270 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -06001271 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001272
1273 // Validate that a valid VkDevice was used, and that the device
1274 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -06001275 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001276 if (!pDevice) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001277 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001278 device,
1279 "VkDevice");
Ian Elliott427058f2015-12-29 16:45:49 -07001280 } else if (!pDevice->swapchainExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001281 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001282 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -08001283 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -07001284 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001285 }
1286
1287 // Regardless of skipCall value, do some internal cleanup:
Tobin Ehlis711ff312015-10-29 12:58:13 -06001288 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001289 if (pSwapchain) {
1290 // Delete the SwpSwapchain associated with this swapchain:
1291 if (pSwapchain->pDevice) {
Chia-I Wue2fc5522015-10-26 20:04:44 +08001292 pSwapchain->pDevice->swapchains.erase(swapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001293 if (device != pSwapchain->pDevice->device) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001294 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001295 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001296 "%s() called with a different VkDevice than the "
1297 "VkSwapchainKHR was created with.",
1298 __FUNCTION__);
1299 }
1300 }
1301 if (pSwapchain->imageCount) {
1302 pSwapchain->images.clear();
1303 }
Tobin Ehlis711ff312015-10-29 12:58:13 -06001304 my_data->swapchainMap.erase(swapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001305 } else {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001306 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
Chia-I Wue2fc5522015-10-26 20:04:44 +08001307 swapchain,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001308 "VkSwapchainKHR");
1309 }
1310
1311 if (VK_FALSE == skipCall) {
1312 // Call down the call chain:
Ian Elliott27d39c72015-11-20 16:39:34 -07001313 my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001314 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001315}
1316
Chia-I Wu9ab61502015-11-06 06:42:02 +08001317VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pCount, VkImage* pSwapchainImages)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001318{
1319 VkResult result = VK_SUCCESS;
1320 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -06001321 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001322
1323 // Validate that a valid VkDevice was used, and that the device
1324 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -06001325 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001326 if (!pDevice) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001327 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001328 device,
1329 "VkDevice");
Ian Elliott427058f2015-12-29 16:45:49 -07001330 } else if (!pDevice->swapchainExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001331 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001332 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -08001333 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -07001334 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001335 }
Tobin Ehlis711ff312015-10-29 12:58:13 -06001336 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001337 if (!pSwapchain) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001338 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001339 swapchain.handle,
1340 "VkSwapchainKHR");
1341 }
1342
1343 if (VK_FALSE == skipCall) {
1344 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -06001345 result = my_data->device_dispatch_table->GetSwapchainImagesKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -06001346 device, swapchain, pCount, pSwapchainImages);
1347
Ian Elliott66463852015-09-28 11:24:53 -06001348// TBD: Should we validate that this function was called once with
1349// pSwapchainImages set to NULL (and record pCount at that time), and then
1350// called again with a non-NULL pSwapchainImages?
Ian Elliott0b4d6242015-09-22 10:51:24 -06001351 if ((result == VK_SUCCESS) && pSwapchain &&pSwapchainImages &&
1352 pCount && (*pCount > 0)) {
1353 // Record the images and their state:
1354 if (pSwapchain) {
1355 pSwapchain->imageCount = *pCount;
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -06001356 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001357 pSwapchain->images[i].image = pSwapchainImages[i];
1358 pSwapchain->images[i].pSwapchain = pSwapchain;
1359 pSwapchain->images[i].ownedByApp = false;
1360 }
1361 }
1362 }
1363
1364 return result;
1365 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07001366 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001367}
1368
Ian Elliott27d39c72015-11-20 16:39:34 -07001369VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR(
1370 VkDevice device,
1371 VkSwapchainKHR swapchain,
1372 uint64_t timeout,
1373 VkSemaphore semaphore,
1374 VkFence fence,
1375 uint32_t* pImageIndex)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001376{
1377// TODO: Record/update the state of the swapchain, in case an error occurs
1378// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
1379 VkResult result = VK_SUCCESS;
1380 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -06001381 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001382
1383 // Validate that a valid VkDevice was used, and that the device
1384 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -06001385 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001386 if (!pDevice) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001387 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001388 device,
1389 "VkDevice");
Ian Elliott427058f2015-12-29 16:45:49 -07001390 } else if (!pDevice->swapchainExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001391 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001392 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -08001393 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -07001394 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001395 }
1396 // Validate that a valid VkSwapchainKHR was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -06001397 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001398 if (!pSwapchain) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001399 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
Chia-I Wue2fc5522015-10-26 20:04:44 +08001400 swapchain,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001401 "VkSwapchainKHR");
1402 } else {
1403 // Look to see if the application is trying to own too many images at
1404 // the same time (i.e. not leave any to display):
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -06001405 uint32_t imagesOwnedByApp = 0;
1406 for (uint32_t i = 0 ; i < pSwapchain->imageCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001407 if (pSwapchain->images[i].ownedByApp) {
1408 imagesOwnedByApp++;
1409 }
1410 }
1411 if (imagesOwnedByApp >= (pSwapchain->imageCount - 1)) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001412 skipCall |= LOG_PERF_WARNING(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
Ian Elliott4a994452015-09-24 18:33:16 -06001413 swapchain,
1414 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001415 SWAPCHAIN_APP_OWNS_TOO_MANY_IMAGES,
Ian Elliott4a994452015-09-24 18:33:16 -06001416 "%s() called when the application "
1417 "already owns all presentable images "
1418 "in this swapchain except for the "
1419 "image currently being displayed. "
1420 "This call to %s() cannot succeed "
1421 "unless another thread calls the "
1422 "vkQueuePresentKHR() function in "
1423 "order to release ownership of one of "
1424 "the presentable images of this "
1425 "swapchain.",
1426 __FUNCTION__, __FUNCTION__);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001427 }
1428 }
1429
1430 if (VK_FALSE == skipCall) {
1431 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -06001432 result = my_data->device_dispatch_table->AcquireNextImageKHR(
Ian Elliott27d39c72015-11-20 16:39:34 -07001433 device, swapchain, timeout, semaphore, fence, pImageIndex);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001434
1435 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) &&
1436 pSwapchain) {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001437 // Change the state of the image (now owned by the application):
1438 pSwapchain->images[*pImageIndex].ownedByApp = true;
1439 }
1440
1441 return result;
1442 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07001443 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001444}
1445
Ian Elliott27d39c72015-11-20 16:39:34 -07001446VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(
1447 VkQueue queue,
1448 const VkPresentInfoKHR* pPresentInfo)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001449{
1450// TODOs:
1451//
1452// - Ensure that the queue is active, and is one of the queueFamilyIndex's
1453// that was returned by a previuos query.
1454// - Record/update the state of the swapchain, in case an error occurs
1455// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
1456 VkResult result = VK_SUCCESS;
1457 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -06001458 layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001459
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -06001460 for (uint32_t i = 0; i < pPresentInfo->swapchainCount ; i++) {
Ian Elliott27d39c72015-11-20 16:39:34 -07001461 uint32_t index = pPresentInfo->pImageIndices[i];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001462 SwpSwapchain *pSwapchain =
Ian Elliott27d39c72015-11-20 16:39:34 -07001463 &my_data->swapchainMap[pPresentInfo->pSwapchains[i]];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001464 if (pSwapchain) {
Ian Elliott427058f2015-12-29 16:45:49 -07001465 if (!pSwapchain->pDevice->swapchainExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001466 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001467 pSwapchain->pDevice, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001468 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -08001469 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -07001470 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001471 }
1472 if (index >= pSwapchain->imageCount) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001473 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -07001474 pPresentInfo->pSwapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001475 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001476 SWAPCHAIN_INDEX_TOO_LARGE,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001477 "%s() called for an index that is too "
1478 "large (i.e. %d). There are only %d "
1479 "images in this VkSwapchainKHR.\n",
1480 __FUNCTION__, index,
1481 pSwapchain->imageCount);
1482 } else {
1483 if (!pSwapchain->images[index].ownedByApp) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001484 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -07001485 pPresentInfo->pSwapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001486 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001487 SWAPCHAIN_INDEX_NOT_IN_USE,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001488 "%s() returned an index (i.e. %d) "
1489 "for an image that is not owned by "
1490 "the application.",
1491 __FUNCTION__, index);
1492 }
1493 }
1494 } else {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001495 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -07001496 pPresentInfo->pSwapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001497 "VkSwapchainKHR");
1498 }
1499 }
1500
1501 if (VK_FALSE == skipCall) {
1502 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -06001503 result = my_data->device_dispatch_table->QueuePresentKHR(queue,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001504 pPresentInfo);
1505
1506 if ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -06001507 for (uint32_t i = 0; i < pPresentInfo->swapchainCount ; i++) {
Ian Elliott27d39c72015-11-20 16:39:34 -07001508 int index = pPresentInfo->pImageIndices[i];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001509 SwpSwapchain *pSwapchain =
Ian Elliott27d39c72015-11-20 16:39:34 -07001510 &my_data->swapchainMap[pPresentInfo->pSwapchains[i]];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001511 if (pSwapchain) {
1512 // Change the state of the image (no longer owned by the
1513 // application):
1514 pSwapchain->images[index].ownedByApp = false;
1515 }
1516 }
1517 }
1518
1519 return result;
1520 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07001521 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001522}
1523
1524static inline PFN_vkVoidFunction layer_intercept_proc(const char *name)
1525{
1526 if (!name || name[0] != 'v' || name[1] != 'k')
1527 return NULL;
1528
1529 name += 2;
1530 if (!strcmp(name, "CreateInstance"))
1531 return (PFN_vkVoidFunction) vkCreateInstance;
1532 if (!strcmp(name, "DestroyInstance"))
1533 return (PFN_vkVoidFunction) vkDestroyInstance;
1534 if (!strcmp(name, "EnumeratePhysicalDevices"))
1535 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
1536 if (!strcmp(name, "CreateDevice"))
1537 return (PFN_vkVoidFunction) vkCreateDevice;
1538 if (!strcmp(name, "DestroyDevice"))
1539 return (PFN_vkVoidFunction) vkDestroyDevice;
1540
1541 return NULL;
1542}
1543static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name)
1544{
1545 if (!name || name[0] != 'v' || name[1] != 'k')
1546 return NULL;
1547
1548 name += 2;
1549 if (!strcmp(name, "CreateInstance"))
1550 return (PFN_vkVoidFunction) vkCreateInstance;
1551 if (!strcmp(name, "DestroyInstance"))
1552 return (PFN_vkVoidFunction) vkDestroyInstance;
1553 if (!strcmp(name, "EnumeratePhysicalDevices"))
1554 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
1555
1556 return NULL;
1557}
1558
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001559VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(
1560 VkInstance instance,
1561 const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
1562 const VkAllocationCallbacks* pAllocator,
1563 VkDebugReportCallbackEXT* pMsgCallback)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001564{
Tobin Ehlis711ff312015-10-29 12:58:13 -06001565 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001566 VkResult result = my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Ian Elliott68124ac2015-10-07 16:18:35 -06001567 if (VK_SUCCESS == result) {
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07001568 result = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback);
Ian Elliott68124ac2015-10-07 16:18:35 -06001569 }
1570 return result;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001571}
1572
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001573VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, const VkAllocationCallbacks *pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001574{
Ian Elliott68124ac2015-10-07 16:18:35 -06001575 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001576 my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07001577 layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001578}
1579
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001580VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07001581 VkInstance instance,
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001582 VkDebugReportFlagsEXT flags,
1583 VkDebugReportObjectTypeEXT objType,
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07001584 uint64_t object,
1585 size_t location,
1586 int32_t msgCode,
1587 const char* pLayerPrefix,
1588 const char* pMsg)
1589{
1590 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001591 my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07001592}
1593
Chia-I Wu9ab61502015-11-06 06:42:02 +08001594VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001595{
1596 PFN_vkVoidFunction addr;
1597 if (device == VK_NULL_HANDLE) {
1598 return NULL;
1599 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001600
Tobin Ehlis711ff312015-10-29 12:58:13 -06001601 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001602 /* loader uses this to force layer initialization; device object is wrapped */
1603 if (!strcmp("vkGetDeviceProcAddr", funcName)) {
Tobin Ehlis711ff312015-10-29 12:58:13 -06001604 VkBaseLayerObject* wrapped_dev = (VkBaseLayerObject*) device;
1605 my_data = get_my_data_ptr(get_dispatch_key(wrapped_dev->baseObject), layer_data_map);
1606 my_data->device_dispatch_table = new VkLayerDispatchTable;
1607 layer_initialize_dispatch_table(my_data->device_dispatch_table, wrapped_dev);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001608 return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
1609 }
1610
1611 addr = layer_intercept_proc(funcName);
1612 if (addr)
1613 return addr;
1614
Tobin Ehlis711ff312015-10-29 12:58:13 -06001615 my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1616 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
1617 if (my_data->deviceMap.size() != 0 &&
Ian Elliott427058f2015-12-29 16:45:49 -07001618 my_data->deviceMap[device].swapchainExtensionEnabled)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001619 {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001620 if (!strcmp("vkCreateSwapchainKHR", funcName))
1621 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateSwapchainKHR);
1622 if (!strcmp("vkDestroySwapchainKHR", funcName))
1623 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySwapchainKHR);
1624 if (!strcmp("vkGetSwapchainImagesKHR", funcName))
1625 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSwapchainImagesKHR);
1626 if (!strcmp("vkAcquireNextImageKHR", funcName))
1627 return reinterpret_cast<PFN_vkVoidFunction>(vkAcquireNextImageKHR);
1628 if (!strcmp("vkQueuePresentKHR", funcName))
1629 return reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR);
1630 }
1631 {
1632 if (pDisp->GetDeviceProcAddr == NULL)
1633 return NULL;
1634 return pDisp->GetDeviceProcAddr(device, funcName);
1635 }
1636}
1637
Chia-I Wu9ab61502015-11-06 06:42:02 +08001638VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001639{
1640 PFN_vkVoidFunction addr;
1641 if (instance == VK_NULL_HANDLE) {
1642 return NULL;
1643 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001644
Tobin Ehlis711ff312015-10-29 12:58:13 -06001645 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001646 /* loader uses this to force layer initialization; instance object is wrapped */
1647 if (!strcmp("vkGetInstanceProcAddr", funcName)) {
Tobin Ehlis711ff312015-10-29 12:58:13 -06001648 VkBaseLayerObject* wrapped_inst = (VkBaseLayerObject*) instance;
1649 my_data = get_my_data_ptr(get_dispatch_key(wrapped_inst->baseObject), layer_data_map);
1650 my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
1651 layer_init_instance_dispatch_table(my_data->instance_dispatch_table, wrapped_inst);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001652 return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
1653 }
1654
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07001655 if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
1656 return (PFN_vkVoidFunction) vkEnumerateInstanceLayerProperties;
1657 if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
1658 return (PFN_vkVoidFunction) vkEnumerateInstanceExtensionProperties;
1659
Ian Elliott0b4d6242015-09-22 10:51:24 -06001660 addr = layer_intercept_instance_proc(funcName);
1661 if (addr)
1662 return addr;
1663
Tobin Ehlis711ff312015-10-29 12:58:13 -06001664 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1665 VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
Ian Elliott68124ac2015-10-07 16:18:35 -06001666 addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
1667 if (addr) {
1668 return addr;
1669 }
1670
Tobin Ehlis711ff312015-10-29 12:58:13 -06001671 if (my_data->instanceMap.size() != 0 &&
Ian Elliott1cb77a62015-12-29 16:44:39 -07001672 my_data->instanceMap[instance].surfaceExtensionEnabled)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001673 {
Ian Elliotta983e9a2015-12-22 12:18:12 -07001674#ifdef VK_USE_PLATFORM_ANDROID_KHR
1675 if (!strcmp("vkCreateAndroidSurfaceKHR", funcName))
1676 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateAndroidSurfaceKHR);
1677#endif // VK_USE_PLATFORM_ANDROID_KHR
1678#ifdef VK_USE_PLATFORM_MIR_KHR
1679 if (!strcmp("vkCreateMirSurfaceKHR", funcName))
1680 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateMirSurfaceKHR);
1681#endif // VK_USE_PLATFORM_MIR_KHR
1682#ifdef VK_USE_PLATFORM_WAYLAND_KHR
1683 if (!strcmp("vkCreateWaylandSurfaceKHR", funcName))
1684 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateWaylandSurfaceKHR);
1685#endif // VK_USE_PLATFORM_WAYLAND_KHR
1686#ifdef VK_USE_PLATFORM_WIN32_KHR
1687 if (!strcmp("vkCreateWin32SurfaceKHR", funcName))
1688 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateWin32SurfaceKHR);
1689#endif // VK_USE_PLATFORM_WIN32_KHR
1690#ifdef VK_USE_PLATFORM_XCB_KHR
1691 if (!strcmp("vkCreateXcbSurfaceKHR", funcName))
1692 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateXcbSurfaceKHR);
1693#endif // VK_USE_PLATFORM_XCB_KHR
1694#ifdef VK_USE_PLATFORM_XLIB_KHR
1695 if (!strcmp("vkCreateXlibSurfaceKHR", funcName))
1696 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateXlibSurfaceKHR);
1697#endif // VK_USE_PLATFORM_XLIB_KHR
1698 if (!strcmp("vkDestroySurfaceKHR", funcName))
1699 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySurfaceKHR);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001700 if (!strcmp("vkGetPhysicalDeviceSurfaceSupportKHR", funcName))
1701 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceSupportKHR);
Ian Elliott27d39c72015-11-20 16:39:34 -07001702 if (!strcmp("vkGetPhysicalDeviceSurfaceCapabilitiesKHR", funcName))
1703 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
1704 if (!strcmp("vkGetPhysicalDeviceSurfaceFormatsKHR", funcName))
1705 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceFormatsKHR);
1706 if (!strcmp("vkGetPhysicalDeviceSurfacePresentModesKHR", funcName))
1707 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfacePresentModesKHR);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001708 }
1709
1710 if (pTable->GetInstanceProcAddr == NULL)
1711 return NULL;
1712 return pTable->GetInstanceProcAddr(instance, funcName);
1713}
1714