blob: 255fb1d5ee2093fa2d8ff3f19058af692f7db569 [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 Elliott0b4d6242015-09-22 10:51:24 -060030#include "swapchain.h"
Tobin Ehlis711ff312015-10-29 12:58:13 -060031#include "vk_layer_extension_utils.h"
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070032#include "vk_enum_string_helper.h"
Ian Elliott68124ac2015-10-07 16:18:35 -060033
Ian Elliott0b4d6242015-09-22 10:51:24 -060034// FIXME/TODO: Make sure this layer is thread-safe!
35
Ian Elliott68124ac2015-10-07 16:18:35 -060036
Ian Elliott0b4d6242015-09-22 10:51:24 -060037// The following is for logging error messages:
Ian Elliott68124ac2015-10-07 16:18:35 -060038static std::unordered_map<void *, layer_data *> layer_data_map;
Ian Elliott0b4d6242015-09-22 10:51:24 -060039
Ian Elliott68124ac2015-10-07 16:18:35 -060040template layer_data *get_my_data_ptr<layer_data>(
41 void *data_key,
42 std::unordered_map<void *, layer_data *> &data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -060043
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -070044static const VkExtensionProperties instance_extensions[] = {
45 {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -070046 VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
47 VK_EXT_DEBUG_REPORT_REVISION
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -070048 }
49};
50
51VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
52 const char *pLayerName,
53 uint32_t *pCount,
54 VkExtensionProperties* pProperties)
55{
56 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
57}
58
59static const VkLayerProperties swapchain_global_layers[] = {
60 {
61 "Swapchain",
62 VK_API_VERSION,
63 VK_MAKE_VERSION(0, 1, 0),
64 "Validation layer: Swapchain",
65 }
66};
67
68VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
69 uint32_t *pCount,
70 VkLayerProperties* pProperties)
71{
72 return util_GetLayerProperties(ARRAY_SIZE(swapchain_global_layers),
73 swapchain_global_layers,
74 pCount, pProperties);
75}
76
Ian Elliott0b4d6242015-09-22 10:51:24 -060077
Ian Elliott0b4d6242015-09-22 10:51:24 -060078static void createDeviceRegisterExtensions(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, VkDevice device)
79{
80 uint32_t i;
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070081 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
82 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -060083
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070084 VkLayerDispatchTable *pDisp = my_device_data->device_dispatch_table;
85 PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr;
86
87 pDisp->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR) gpa(device, "vkCreateSwapchainKHR");
88 pDisp->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR) gpa(device, "vkDestroySwapchainKHR");
89 pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR) gpa(device, "vkGetSwapchainImagesKHR");
90 pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR) gpa(device, "vkAcquireNextImageKHR");
91 pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR) gpa(device, "vkQueuePresentKHR");
92
93 SwpPhysicalDevice *pPhysicalDevice = &my_instance_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -060094 if (pPhysicalDevice) {
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070095 my_device_data->deviceMap[device].pPhysicalDevice = pPhysicalDevice;
96 pPhysicalDevice->pDevice = &my_device_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -060097 } else {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -070098 log_msg(my_instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070099 (uint64_t)physicalDevice , 0, SWAPCHAIN_INVALID_HANDLE, "Swapchain",
100 "vkCreateDevice() called with a non-valid VkPhysicalDevice.");
Ian Elliott0b4d6242015-09-22 10:51:24 -0600101 }
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700102 my_device_data->deviceMap[device].device = device;
103 my_device_data->deviceMap[device].deviceSwapchainExtensionEnabled = false;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600104
105 // Record whether the WSI device extension was enabled for this VkDevice.
106 // No need to check if the extension was advertised by
107 // vkEnumerateDeviceExtensionProperties(), since the loader handles that.
Chia-I Wud50a7d72015-10-26 20:48:51 +0800108 for (i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Ian Elliott1dcd1092015-11-17 17:29:40 -0700109 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600110
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700111 my_device_data->deviceMap[device].deviceSwapchainExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600112 }
113 }
114}
115
116static void createInstanceRegisterExtensions(const VkInstanceCreateInfo* pCreateInfo, VkInstance instance)
117{
118 uint32_t i;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600119 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
120 VkLayerInstanceDispatchTable *pDisp = my_data->instance_dispatch_table;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600121 PFN_vkGetInstanceProcAddr gpa = pDisp->GetInstanceProcAddr;
122 pDisp->GetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceSupportKHR");
Ian Elliott27d39c72015-11-20 16:39:34 -0700123 pDisp->GetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
124 pDisp->GetPhysicalDeviceSurfaceFormatsKHR = (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR");
125 pDisp->GetPhysicalDeviceSurfacePresentModesKHR = (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR) gpa(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR");
Ian Elliott0b4d6242015-09-22 10:51:24 -0600126
Ian Elliott1dcd1092015-11-17 17:29:40 -0700127 // Remember this instance, and whether the VK_KHR_surface extension
Ian Elliott0b4d6242015-09-22 10:51:24 -0600128 // was enabled for it:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600129 my_data->instanceMap[instance].instance = instance;
130 my_data->instanceMap[instance].swapchainExtensionEnabled = false;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600131
132 // Record whether the WSI instance extension was enabled for this
133 // VkInstance. No need to check if the extension was advertised by
134 // vkEnumerateInstanceExtensionProperties(), since the loader handles that.
Chia-I Wud50a7d72015-10-26 20:48:51 +0800135 for (i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Ian Elliott1dcd1092015-11-17 17:29:40 -0700136 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600137
Tobin Ehlis711ff312015-10-29 12:58:13 -0600138 my_data->instanceMap[instance].swapchainExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600139 }
140 }
141}
142
143
144#include "vk_dispatch_table_helper.h"
Courtney Goeltzenleuchter6d8e8182015-11-25 14:31:49 -0700145static void initSwapchain(layer_data *my_data, const VkAllocationCallbacks *pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600146{
147 uint32_t report_flags = 0;
148 uint32_t debug_action = 0;
149 FILE *log_output = NULL;
150 const char *option_str;
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700151 VkDebugReportCallbackEXT callback;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600152
153 // Initialize Swapchain options:
154 report_flags = getLayerOptionFlags("SwapchainReportFlags", 0);
155 getLayerOptionEnum("SwapchainDebugAction", (uint32_t *) &debug_action);
156
157 if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)
158 {
159 // Turn on logging, since it was requested:
160 option_str = getLayerOption("SwapchainLogFilename");
161 log_output = getLayerLogOutput(option_str, "Swapchain");
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700162 VkDebugReportCallbackCreateInfoEXT dbgInfo;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700163 memset(&dbgInfo, 0, sizeof(dbgInfo));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700164 dbgInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700165 dbgInfo.pfnCallback = log_callback;
166 dbgInfo.pUserData = log_output;
167 dbgInfo.flags = report_flags;
168 layer_create_msg_callback(my_data->report_data,
169 &dbgInfo,
170 pAllocator,
Courtney Goeltzenleuchtercf60e0a2015-10-08 17:07:25 -0600171 &callback);
172 my_data->logging_callback.push_back(callback);
173 }
174 if (debug_action & VK_DBG_LAYER_ACTION_DEBUG_OUTPUT) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700175 VkDebugReportCallbackCreateInfoEXT dbgInfo;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700176 memset(&dbgInfo, 0, sizeof(dbgInfo));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700177 dbgInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700178 dbgInfo.pfnCallback = win32_debug_output_msg;
179 dbgInfo.pUserData = log_output;
180 dbgInfo.flags = report_flags;
181 layer_create_msg_callback(my_data->report_data, &dbgInfo, pAllocator, &callback);
Courtney Goeltzenleuchtercf60e0a2015-10-08 17:07:25 -0600182 my_data->logging_callback.push_back(callback);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600183 }
184}
185
Ian Elliott27d39c72015-11-20 16:39:34 -0700186static const char *surfaceTransformStr(VkSurfaceTransformFlagBitsKHR value)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600187{
Ian Elliott0b4d6242015-09-22 10:51:24 -0600188
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700189 // TODO: parse flags and print out one at a time
Ian Elliott0b4d6242015-09-22 10:51:24 -0600190 // Return a string corresponding to the value:
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700191 return string_VkSurfaceTransformFlagBitsKHR(value);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600192}
193
194static const char *presentModeStr(VkPresentModeKHR value)
195{
196 static std::string presentModeStrings[] = {
197 "VK_PRESENT_MODE_IMMEDIATE_KHR",
198 "VK_PRESENT_MODE_MAILBOX_KHR",
199 "VK_PRESENT_MODE_FIFO_KHR",
200 "Out-of-Range Value"};
201
202 // Deal with a out-of-range value:
203 switch (value) {
204 case VK_PRESENT_MODE_IMMEDIATE_KHR:
205 case VK_PRESENT_MODE_MAILBOX_KHR:
206 case VK_PRESENT_MODE_FIFO_KHR:
207 break;
208 default:
209 value = (VkPresentModeKHR) (VK_PRESENT_MODE_FIFO_KHR + 1);
210 break;
211 }
212
213 // Return a string corresponding to the value:
214 return presentModeStrings[value].c_str();
215}
216
217
Chia-I Wu9ab61502015-11-06 06:42:02 +0800218VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600219{
Tobin Ehlis711ff312015-10-29 12:58:13 -0600220 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600221 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600222 VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
Chia-I Wuf7458c52015-10-26 21:10:41 +0800223 VkResult result = pTable->CreateInstance(pCreateInfo, pAllocator, pInstance);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600224 if (result == VK_SUCCESS) {
225 // Since it succeeded, do layer-specific work:
Ian Elliott68124ac2015-10-07 16:18:35 -0600226 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
227 my_data->report_data = debug_report_create_instance(
Tobin Ehlis711ff312015-10-29 12:58:13 -0600228 pTable,
Ian Elliott68124ac2015-10-07 16:18:35 -0600229 *pInstance,
Chia-I Wud50a7d72015-10-26 20:48:51 +0800230 pCreateInfo->enabledExtensionNameCount,
Ian Elliott68124ac2015-10-07 16:18:35 -0600231 pCreateInfo->ppEnabledExtensionNames);
232 // Call the following function after my_data is initialized:
Ian Elliott0b4d6242015-09-22 10:51:24 -0600233 createInstanceRegisterExtensions(pCreateInfo, *pInstance);
Courtney Goeltzenleuchter6d8e8182015-11-25 14:31:49 -0700234 initSwapchain(my_data, pAllocator);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600235 }
236 return result;
237}
238
Chia-I Wu9ab61502015-11-06 06:42:02 +0800239VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600240{
241 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600242 dispatch_key key = get_dispatch_key(instance);
243 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600244 // Validate that a valid VkInstance was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600245 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600246 if (!pInstance) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700247 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600248 instance,
249 "VkInstance");
250 }
251
252 if (VK_FALSE == skipCall) {
253 // Call down the call chain:
Chia-I Wuf7458c52015-10-26 21:10:41 +0800254 my_data->instance_dispatch_table->DestroyInstance(instance, pAllocator);
Ian Elliott68124ac2015-10-07 16:18:35 -0600255
256 // Clean up logging callback, if any
Courtney Goeltzenleuchtercf60e0a2015-10-08 17:07:25 -0600257 while (my_data->logging_callback.size() > 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700258 VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700259 layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
Courtney Goeltzenleuchtercf60e0a2015-10-08 17:07:25 -0600260 my_data->logging_callback.pop_back();
Ian Elliott68124ac2015-10-07 16:18:35 -0600261 }
262 layer_debug_report_destroy_instance(my_data->report_data);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600263 }
264
265 // Regardless of skipCall value, do some internal cleanup:
266 if (pInstance) {
267 // Delete all of the SwpPhysicalDevice's and the SwpInstance associated
268 // with this instance:
269 for (auto it = pInstance->physicalDevices.begin() ;
270 it != pInstance->physicalDevices.end() ; it++) {
Ian Elliott27d39c72015-11-20 16:39:34 -0700271
272 // Free memory that was allocated for/by this SwpPhysicalDevice:
273 SwpPhysicalDevice *pPhysicalDevice = it->second;
274 free(pPhysicalDevice->pSurfaceFormats);
275 free(pPhysicalDevice->pPresentModes);
276
Tobin Ehlis711ff312015-10-29 12:58:13 -0600277 // Erase the SwpPhysicalDevice's from the my_data->physicalDeviceMap (which
Ian Elliott0b4d6242015-09-22 10:51:24 -0600278 // are simply pointed to by the SwpInstance):
Tobin Ehlis711ff312015-10-29 12:58:13 -0600279 my_data->physicalDeviceMap.erase(it->second->physicalDevice);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600280 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600281 my_data->instanceMap.erase(instance);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600282 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600283 delete my_data->instance_dispatch_table;
284 layer_data_map.erase(key);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600285}
286
Chia-I Wu9ab61502015-11-06 06:42:02 +0800287VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600288{
289 VkResult result = VK_SUCCESS;
290 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600291 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600292
293 // Validate that a valid VkInstance was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600294 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600295 if (!pInstance) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700296 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600297 instance,
298 "VkInstance");
299 }
300
301 if (VK_FALSE == skipCall) {
302 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600303 result = my_data->instance_dispatch_table->EnumeratePhysicalDevices(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600304 instance, pPhysicalDeviceCount, pPhysicalDevices);
305
306 if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices &&
307 (*pPhysicalDeviceCount > 0)) {
308 // Record the VkPhysicalDevices returned by the ICD:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600309 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600310 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
Tobin Ehlis711ff312015-10-29 12:58:13 -0600311 my_data->physicalDeviceMap[pPhysicalDevices[i]].physicalDevice =
Ian Elliott0b4d6242015-09-22 10:51:24 -0600312 pPhysicalDevices[i];
Tobin Ehlis711ff312015-10-29 12:58:13 -0600313 my_data->physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance;
314 my_data->physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL;
Ian Elliott27d39c72015-11-20 16:39:34 -0700315 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotSurfaceCapabilities = false;
316 my_data->physicalDeviceMap[pPhysicalDevices[i]].surfaceFormatCount = 0;
317 my_data->physicalDeviceMap[pPhysicalDevices[i]].pSurfaceFormats = NULL;
318 my_data->physicalDeviceMap[pPhysicalDevices[i]].presentModeCount = 0;
319 my_data->physicalDeviceMap[pPhysicalDevices[i]].pPresentModes = NULL;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600320 // Point to the associated SwpInstance:
321 pInstance->physicalDevices[pPhysicalDevices[i]] =
Tobin Ehlis711ff312015-10-29 12:58:13 -0600322 &my_data->physicalDeviceMap[pPhysicalDevices[i]];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600323 }
324 }
325
326 return result;
327 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700328 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600329}
330
Chia-I Wu9ab61502015-11-06 06:42:02 +0800331VK_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 -0600332{
333 VkResult result = VK_SUCCESS;
334 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600335 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600336
337 // Validate that a valid VkPhysicalDevice was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600338 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600339 if (!pPhysicalDevice) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700340 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
Mark Lobodzinski6c1cb5a2015-11-05 15:27:03 -0700341 physicalDevice, "VkPhysicalDevice");
Ian Elliott0b4d6242015-09-22 10:51:24 -0600342 }
343
Tobin Ehlis711ff312015-10-29 12:58:13 -0600344 if (VK_TRUE == skipCall)
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700345 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600346
347 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
348 // Call down the call chain:
349 result = my_device_data->device_dispatch_table->CreateDevice(
Chia-I Wuf7458c52015-10-26 21:10:41 +0800350 physicalDevice, pCreateInfo, pAllocator, pDevice);
Tobin Ehlis711ff312015-10-29 12:58:13 -0600351 if (result == VK_SUCCESS) {
352 // Since it succeeded, do layer-specific work:
Mark Lobodzinski6c1cb5a2015-11-05 15:27:03 -0700353 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
354 my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
355 createDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600356 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600357 return result;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600358}
359
Chia-I Wu9ab61502015-11-06 06:42:02 +0800360VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600361{
362 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600363 dispatch_key key = get_dispatch_key(device);
364 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600365 // Validate that a valid VkDevice was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600366 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600367 if (!pDevice) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700368 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600369 device,
370 "VkDevice");
371 }
372
373 if (VK_FALSE == skipCall) {
374 // Call down the call chain:
Chia-I Wuf7458c52015-10-26 21:10:41 +0800375 my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600376 }
377
378 // Regardless of skipCall value, do some internal cleanup:
379 if (pDevice) {
380 // Delete the SwpDevice associated with this device:
381 if (pDevice->pPhysicalDevice) {
382 pDevice->pPhysicalDevice->pDevice = NULL;
383 }
Ian Elliott0b4d6242015-09-22 10:51:24 -0600384 if (!pDevice->swapchains.empty()) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700385 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600386 SWAPCHAIN_DEL_DEVICE_BEFORE_SWAPCHAINS,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600387 "%s() called before all of its associated "
388 "VkSwapchainKHRs were destroyed.",
389 __FUNCTION__);
390 // Empty and then delete all SwpSwapchain's
391 for (auto it = pDevice->swapchains.begin() ;
392 it != pDevice->swapchains.end() ; it++) {
393 // Delete all SwpImage's
394 it->second->images.clear();
395 }
396 pDevice->swapchains.clear();
397 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600398 my_data->deviceMap.erase(device);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600399 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600400 delete my_data->device_dispatch_table;
401 layer_data_map.erase(key);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600402}
403
Ian Elliott27d39c72015-11-20 16:39:34 -0700404VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(
405 VkPhysicalDevice physicalDevice,
406 uint32_t queueFamilyIndex,
407 VkSurfaceKHR surface,
408 VkBool32* pSupported)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600409{
410 VkResult result = VK_SUCCESS;
411 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600412 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600413
414 // Validate that a valid VkPhysicalDevice was used, and that the instance
415 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600416 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600417 if (!pPhysicalDevice || !pPhysicalDevice->pInstance) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700418 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600419 physicalDevice,
420 "VkPhysicalDevice");
421 } else if (!pPhysicalDevice->pInstance->swapchainExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700422 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600423 pPhysicalDevice->pInstance,
424 "VkInstance",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600425 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800426 "%s() called even though the %s extension was not enabled for this VkInstance.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700427 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600428 }
429
430 if (VK_FALSE == skipCall) {
431 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600432 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(
Ian Elliott27d39c72015-11-20 16:39:34 -0700433 physicalDevice, queueFamilyIndex, surface,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600434 pSupported);
435
436 if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
437 // Record the result of this query:
438 pPhysicalDevice->queueFamilyIndexSupport[queueFamilyIndex] =
439 *pSupported;
440 // TODO: We need to compare this with the actual queue used for
441 // presentation, to ensure it was advertised to the application as
442 // supported for presentation.
443 }
444
445 return result;
446 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700447 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600448}
449
Ian Elliott27d39c72015-11-20 16:39:34 -0700450VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
451 VkPhysicalDevice physicalDevice,
452 VkSurfaceKHR surface,
453 VkSurfaceCapabilitiesKHR* pSurfaceCapabilities)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600454{
455 VkResult result = VK_SUCCESS;
456 VkBool32 skipCall = VK_FALSE;
Ian Elliott27d39c72015-11-20 16:39:34 -0700457 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600458
Ian Elliott27d39c72015-11-20 16:39:34 -0700459 // Validate that a valid VkPhysicalDevice was used, and that the instance
Ian Elliott0b4d6242015-09-22 10:51:24 -0600460 // extension was enabled:
Ian Elliott27d39c72015-11-20 16:39:34 -0700461 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
462 if (!pPhysicalDevice || !pPhysicalDevice->pInstance) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700463 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -0700464 physicalDevice,
465 "VkPhysicalDevice");
466 } else if (!pPhysicalDevice->pInstance->swapchainExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700467 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -0700468 pPhysicalDevice->pInstance,
469 "VkInstance",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600470 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott27d39c72015-11-20 16:39:34 -0700471 "%s() called even though the %s extension was not enabled for this VkInstance.",
472 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600473 }
474
475 if (VK_FALSE == skipCall) {
476 // Call down the call chain:
Ian Elliott27d39c72015-11-20 16:39:34 -0700477 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceCapabilitiesKHR(
478 physicalDevice, surface, pSurfaceCapabilities);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600479
Ian Elliott27d39c72015-11-20 16:39:34 -0700480 if ((result == VK_SUCCESS) && pPhysicalDevice) {
481 pPhysicalDevice->gotSurfaceCapabilities = true;
482// FIXME: NEED TO COPY THIS DATA, BECAUSE pSurfaceCapabilities POINTS TO APP-ALLOCATED DATA
483 pPhysicalDevice->surfaceCapabilities = *pSurfaceCapabilities;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600484 }
485
486 return result;
487 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700488 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600489}
490
Ian Elliott27d39c72015-11-20 16:39:34 -0700491VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR(
492 VkPhysicalDevice physicalDevice,
493 VkSurfaceKHR surface,
494 uint32_t* pCount,
495 VkSurfaceFormatKHR* pSurfaceFormats)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600496{
497 VkResult result = VK_SUCCESS;
498 VkBool32 skipCall = VK_FALSE;
Ian Elliott27d39c72015-11-20 16:39:34 -0700499 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600500
Ian Elliott27d39c72015-11-20 16:39:34 -0700501 // Validate that a valid VkPhysicalDevice was used, and that the instance
Ian Elliott0b4d6242015-09-22 10:51:24 -0600502 // extension was enabled:
Ian Elliott27d39c72015-11-20 16:39:34 -0700503 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
504 if (!pPhysicalDevice || !pPhysicalDevice->pInstance) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700505 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -0700506 physicalDevice,
507 "VkPhysicalDevice");
508 } else if (!pPhysicalDevice->pInstance->swapchainExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700509 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -0700510 pPhysicalDevice->pInstance,
511 "VkInstance",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600512 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott27d39c72015-11-20 16:39:34 -0700513 "%s() called even though the %s extension was not enabled for this VkInstance.",
514 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600515 }
516
517 if (VK_FALSE == skipCall) {
518 // Call down the call chain:
Ian Elliott27d39c72015-11-20 16:39:34 -0700519 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceFormatsKHR(
520 physicalDevice, surface, pCount, pSurfaceFormats);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600521
Ian Elliott27d39c72015-11-20 16:39:34 -0700522 if ((result == VK_SUCCESS) && pPhysicalDevice && pSurfaceFormats && pCount &&
Ian Elliott0b4d6242015-09-22 10:51:24 -0600523 (*pCount > 0)) {
Ian Elliott27d39c72015-11-20 16:39:34 -0700524 pPhysicalDevice->surfaceFormatCount = *pCount;
525 pPhysicalDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600526 malloc(*pCount * sizeof(VkSurfaceFormatKHR));
Ian Elliott27d39c72015-11-20 16:39:34 -0700527 if (pPhysicalDevice->pSurfaceFormats) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600528 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott27d39c72015-11-20 16:39:34 -0700529 pPhysicalDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600530 }
531 } else {
Ian Elliott27d39c72015-11-20 16:39:34 -0700532 pPhysicalDevice->surfaceFormatCount = 0;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600533 }
534 }
535
536 return result;
537 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700538 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600539}
540
Ian Elliott27d39c72015-11-20 16:39:34 -0700541VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR(
542 VkPhysicalDevice physicalDevice,
543 VkSurfaceKHR surface,
544 uint32_t* pCount,
545 VkPresentModeKHR* pPresentModes)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600546{
547 VkResult result = VK_SUCCESS;
548 VkBool32 skipCall = VK_FALSE;
Ian Elliott27d39c72015-11-20 16:39:34 -0700549 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600550
Ian Elliott27d39c72015-11-20 16:39:34 -0700551 // Validate that a valid VkPhysicalDevice was used, and that the instance
Ian Elliott0b4d6242015-09-22 10:51:24 -0600552 // extension was enabled:
Ian Elliott27d39c72015-11-20 16:39:34 -0700553 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
554 if (!pPhysicalDevice || !pPhysicalDevice->pInstance) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700555 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -0700556 physicalDevice,
557 "VkPhysicalDevice");
558 } else if (!pPhysicalDevice->pInstance->swapchainExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700559 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -0700560 pPhysicalDevice->pInstance,
561 "VkInstance",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600562 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott27d39c72015-11-20 16:39:34 -0700563 "%s() called even though the %s extension was not enabled for this VkInstance.",
564 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600565 }
566
567 if (VK_FALSE == skipCall) {
568 // Call down the call chain:
Ian Elliott27d39c72015-11-20 16:39:34 -0700569 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfacePresentModesKHR(
570 physicalDevice, surface, pCount, pPresentModes);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600571
Ian Elliott27d39c72015-11-20 16:39:34 -0700572 if ((result == VK_SUCCESS) && pPhysicalDevice && pPresentModes && pCount &&
Ian Elliott0b4d6242015-09-22 10:51:24 -0600573 (*pCount > 0)) {
Ian Elliott27d39c72015-11-20 16:39:34 -0700574 pPhysicalDevice->presentModeCount = *pCount;
575 pPhysicalDevice->pPresentModes = (VkPresentModeKHR *)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600576 malloc(*pCount * sizeof(VkPresentModeKHR));
Ian Elliott27d39c72015-11-20 16:39:34 -0700577 if (pPhysicalDevice->pSurfaceFormats) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600578 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott27d39c72015-11-20 16:39:34 -0700579 pPhysicalDevice->pPresentModes[i] = pPresentModes[i];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600580 }
581 } else {
Ian Elliott27d39c72015-11-20 16:39:34 -0700582 pPhysicalDevice->presentModeCount = 0;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600583 }
584 }
585
586 return result;
587 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700588 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600589}
590
591// This function does the up-front validation work for vkCreateSwapchainKHR(),
592// and returns VK_TRUE if a logging callback indicates that the call down the
593// chain should be skipped:
594static VkBool32 validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, VkSwapchainKHR* pSwapchain)
595{
596// TODO: Validate cases of re-creating a swapchain (the current code
597// assumes a new swapchain is being created).
598 VkResult result = VK_SUCCESS;
599 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600600 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600601 char fn[] = "vkCreateSwapchainKHR";
602
603 // Validate that a valid VkDevice was used, and that the device
604 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600605 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600606 if (!pDevice) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700607 return LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600608 SWAPCHAIN_INVALID_HANDLE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600609 "%s() called with a non-valid %s.",
610 fn, "VkDevice");
611
612 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700613 return LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600614 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800615 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700616 fn, VK_KHR_SWAPCHAIN_EXTENSION_NAME );
Ian Elliott0b4d6242015-09-22 10:51:24 -0600617 }
618
619 // Validate pCreateInfo with the results for previous queries:
Ian Elliott27d39c72015-11-20 16:39:34 -0700620 if (!pDevice->pPhysicalDevice && !pDevice->pPhysicalDevice->gotSurfaceCapabilities) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700621 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600622 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600623 "%s() called before calling "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700624 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
Ian Elliott0b4d6242015-09-22 10:51:24 -0600625 fn);
626 } else {
627 // Validate pCreateInfo->minImageCount against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700628 // VkSurfaceCapabilitiesKHR::{min|max}ImageCount:
Ian Elliott27d39c72015-11-20 16:39:34 -0700629 VkSurfaceCapabilitiesKHR *pCapabilities = &pDevice->pPhysicalDevice->surfaceCapabilities;
630 if ((pCreateInfo->minImageCount < pCapabilities->minImageCount) ||
631 ((pCapabilities->maxImageCount > 0) &&
632 (pCreateInfo->minImageCount > pCapabilities->maxImageCount))) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700633 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600634 SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600635 "%s() called with pCreateInfo->minImageCount "
636 "= %d, which is outside the bounds returned "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700637 "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. "
Ian Elliott0b4d6242015-09-22 10:51:24 -0600638 "minImageCount = %d, maxImageCount = %d).",
639 fn,
640 pCreateInfo->minImageCount,
Ian Elliott27d39c72015-11-20 16:39:34 -0700641 pCapabilities->minImageCount,
642 pCapabilities->maxImageCount);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600643 }
644 // Validate pCreateInfo->imageExtent against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700645 // VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
Ian Elliott27d39c72015-11-20 16:39:34 -0700646 if ((pCapabilities->currentExtent.width == -1) &&
647 ((pCreateInfo->imageExtent.width < pCapabilities->minImageExtent.width) ||
648 (pCreateInfo->imageExtent.width > pCapabilities->maxImageExtent.width) ||
649 (pCreateInfo->imageExtent.height < pCapabilities->minImageExtent.height) ||
650 (pCreateInfo->imageExtent.height > pCapabilities->maxImageExtent.height))) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700651 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600652 SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600653 "%s() called with pCreateInfo->imageExtent = "
654 "(%d,%d), which is outside the bounds "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700655 "returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): "
Ian Elliott0b4d6242015-09-22 10:51:24 -0600656 "currentExtent = (%d,%d), minImageExtent = "
657 "(%d,%d), maxImageExtent = (%d,%d).",
658 fn,
659 pCreateInfo->imageExtent.width,
660 pCreateInfo->imageExtent.height,
Ian Elliott27d39c72015-11-20 16:39:34 -0700661 pCapabilities->currentExtent.width,
662 pCapabilities->currentExtent.height,
663 pCapabilities->minImageExtent.width,
664 pCapabilities->minImageExtent.height,
665 pCapabilities->maxImageExtent.width,
666 pCapabilities->maxImageExtent.height);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600667 }
Ian Elliott27d39c72015-11-20 16:39:34 -0700668 if ((pCapabilities->currentExtent.width != -1) &&
669 ((pCreateInfo->imageExtent.width != pCapabilities->currentExtent.width) ||
670 (pCreateInfo->imageExtent.height != pCapabilities->currentExtent.height))) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700671 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600672 SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600673 "%s() called with pCreateInfo->imageExtent = "
674 "(%d,%d), which is not equal to the "
675 "currentExtent = (%d,%d) returned by "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700676 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
Ian Elliott0b4d6242015-09-22 10:51:24 -0600677 fn,
678 pCreateInfo->imageExtent.width,
679 pCreateInfo->imageExtent.height,
Ian Elliott27d39c72015-11-20 16:39:34 -0700680 pCapabilities->currentExtent.width,
681 pCapabilities->currentExtent.height);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600682 }
683 // Validate pCreateInfo->preTransform against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700684 // VkSurfaceCapabilitiesKHR::supportedTransforms:
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700685 if (!((pCreateInfo->preTransform) & pCapabilities->supportedTransforms)) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600686 // This is an error situation; one for which we'd like to give
687 // the developer a helpful, multi-line error message. Build it
688 // up a little at a time, and then log it:
689 std::string errorString = "";
690 char str[1024];
691 // Here's the first part of the message:
692 sprintf(str, "%s() called with a non-supported "
693 "pCreateInfo->preTransform (i.e. %s). "
694 "Supported values are:\n",
695 fn,
696 surfaceTransformStr(pCreateInfo->preTransform));
697 errorString += str;
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700698 for (int i = 0; i < 32; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600699 // Build up the rest of the message:
Ian Elliott27d39c72015-11-20 16:39:34 -0700700 if ((1 << i) & pCapabilities->supportedTransforms) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600701 const char *newStr =
Ian Elliott27d39c72015-11-20 16:39:34 -0700702 surfaceTransformStr((VkSurfaceTransformFlagBitsKHR) (1 << i));
Ian Elliott0b4d6242015-09-22 10:51:24 -0600703 sprintf(str, " %s\n", newStr);
704 errorString += str;
705 }
706 }
707 // Log the message that we've built up:
Ian Elliott68124ac2015-10-07 16:18:35 -0600708 skipCall |= debug_report_log_msg(my_data->report_data,
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700709 VK_DEBUG_REPORT_ERROR_BIT_EXT,
710 VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700711 (uint64_t) device, 0,
Ian Elliottb0f474c2015-09-25 15:50:55 -0600712 SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM,
713 LAYER_NAME,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600714 errorString.c_str());
715 }
716 // Validate pCreateInfo->imageArraySize against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700717 // VkSurfaceCapabilitiesKHR::maxImageArraySize:
Mark Lobodzinskia3b44522015-12-11 11:05:33 -0700718 if (pCreateInfo->imageArrayLayers > pCapabilities->maxImageArrayLayers) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700719 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600720 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_SIZE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600721 "%s() called with a non-supported "
722 "pCreateInfo->imageArraySize (i.e. %d). "
723 "Maximum value is %d.",
724 fn,
Ian Elliott27d39c72015-11-20 16:39:34 -0700725 pCreateInfo->imageArrayLayers,
726 pCapabilities->maxImageArrayLayers);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600727 }
Ian Elliott27d39c72015-11-20 16:39:34 -0700728 // Validate pCreateInfo->imageUsage against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700729 // VkSurfaceCapabilitiesKHR::supportedUsageFlags:
Ian Elliott27d39c72015-11-20 16:39:34 -0700730 if (pCreateInfo->imageUsage &&
731 (pCreateInfo->imageUsage !=
732 (pCreateInfo->imageUsage & pCapabilities->supportedUsageFlags))) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700733 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600734 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600735 "%s() called with a non-supported "
Ian Elliott27d39c72015-11-20 16:39:34 -0700736 "pCreateInfo->imageUsage (i.e. 0x%08x)."
Ian Elliott0b4d6242015-09-22 10:51:24 -0600737 " Supported flag bits are 0x%08x.",
738 fn,
Ian Elliott27d39c72015-11-20 16:39:34 -0700739 pCreateInfo->imageUsage,
740 pCapabilities->supportedUsageFlags);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600741 }
742 }
Ian Elliott27d39c72015-11-20 16:39:34 -0700743 if (!pDevice->pPhysicalDevice && !pDevice->pPhysicalDevice->surfaceFormatCount) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700744 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600745 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600746 "%s() called before calling "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700747 "vkGetPhysicalDeviceSurfaceFormatsKHR().",
Ian Elliott0b4d6242015-09-22 10:51:24 -0600748 fn);
749 } else {
750 // Validate pCreateInfo->imageFormat against
751 // VkSurfaceFormatKHR::format:
752 bool foundFormat = false;
753 bool foundColorSpace = false;
754 bool foundMatch = false;
Ian Elliott27d39c72015-11-20 16:39:34 -0700755 for (uint32_t i = 0 ; i < pDevice->pPhysicalDevice->surfaceFormatCount ; i++) {
756 if (pCreateInfo->imageFormat == pDevice->pPhysicalDevice->pSurfaceFormats[i].format) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600757 // Validate pCreateInfo->imageColorSpace against
758 // VkSurfaceFormatKHR::colorSpace:
759 foundFormat = true;
Ian Elliott27d39c72015-11-20 16:39:34 -0700760 if (pCreateInfo->imageColorSpace == pDevice->pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600761 foundMatch = true;
762 break;
763 }
764 } else {
Ian Elliott27d39c72015-11-20 16:39:34 -0700765 if (pCreateInfo->imageColorSpace == pDevice->pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600766 foundColorSpace = true;
767 }
768 }
769 }
770 if (!foundMatch) {
771 if (!foundFormat) {
772 if (!foundColorSpace) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700773 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600774 "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600775 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600776 "%s() called with neither a "
777 "supported pCreateInfo->imageFormat "
778 "(i.e. %d) nor a supported "
779 "pCreateInfo->imageColorSpace "
780 "(i.e. %d).",
781 fn,
782 pCreateInfo->imageFormat,
783 pCreateInfo->imageColorSpace);
784 } else {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700785 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device,
Ian Elliottb0f474c2015-09-25 15:50:55 -0600786 "VkDevice",
787 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600788 "%s() called with a non-supported "
789 "pCreateInfo->imageFormat (i.e. %d).",
790 fn, pCreateInfo->imageFormat);
791 }
792 } else if (!foundColorSpace) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700793 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600794 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600795 "%s() called with a non-supported "
796 "pCreateInfo->imageColorSpace (i.e. %d).",
797 fn, pCreateInfo->imageColorSpace);
798 }
799 }
800 }
Ian Elliott27d39c72015-11-20 16:39:34 -0700801 if (!pDevice->pPhysicalDevice && !pDevice->pPhysicalDevice->presentModeCount) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700802 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600803 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600804 "%s() called before calling "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700805 "vkGetPhysicalDeviceSurfacePresentModesKHR().",
Ian Elliott0b4d6242015-09-22 10:51:24 -0600806 fn);
807 } else {
808 // Validate pCreateInfo->presentMode against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700809 // vkGetPhysicalDeviceSurfacePresentModesKHR():
Ian Elliott0b4d6242015-09-22 10:51:24 -0600810 bool foundMatch = false;
Ian Elliott27d39c72015-11-20 16:39:34 -0700811 for (uint32_t i = 0 ; i < pDevice->pPhysicalDevice->presentModeCount ; i++) {
812 if (pDevice->pPhysicalDevice->pPresentModes[i] == pCreateInfo->presentMode) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600813 foundMatch = true;
814 break;
815 }
816 }
817 if (!foundMatch) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700818 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600819 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600820 "%s() called with a non-supported "
821 "pCreateInfo->presentMode (i.e. %s).",
822 fn,
823 presentModeStr(pCreateInfo->presentMode));
824 }
825 }
826
827 // TODO: Validate the following values:
828 // - pCreateInfo->sharingMode
Chia-I Wud50a7d72015-10-26 20:48:51 +0800829 // - pCreateInfo->queueFamilyIndexCount
Ian Elliott0b4d6242015-09-22 10:51:24 -0600830 // - pCreateInfo->pQueueFamilyIndices
831 // - pCreateInfo->oldSwapchain
832
833 return skipCall;
834}
835
Ian Elliott27d39c72015-11-20 16:39:34 -0700836VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(
837 VkDevice device,
838 const VkSwapchainCreateInfoKHR* pCreateInfo,
839 const VkAllocationCallbacks* pAllocator,
840 VkSwapchainKHR* pSwapchain)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600841{
842 VkResult result = VK_SUCCESS;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600843 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600844 VkBool32 skipCall = validateCreateSwapchainKHR(device, pCreateInfo,
845 pSwapchain);
846
847 if (VK_FALSE == skipCall) {
848 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600849 result = my_data->device_dispatch_table->CreateSwapchainKHR(
Ian Elliott27d39c72015-11-20 16:39:34 -0700850 device, pCreateInfo, pAllocator, pSwapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600851
852 if (result == VK_SUCCESS) {
853 // Remember the swapchain's handle, and link it to the device:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600854 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600855
Tobin Ehlis711ff312015-10-29 12:58:13 -0600856 my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
Chia-I Wue2fc5522015-10-26 20:04:44 +0800857 pDevice->swapchains[*pSwapchain] =
Tobin Ehlis711ff312015-10-29 12:58:13 -0600858 &my_data->swapchainMap[*pSwapchain];
859 my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
860 my_data->swapchainMap[*pSwapchain].imageCount = 0;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600861 }
862
863 return result;
864 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700865 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600866}
867
Ian Elliott27d39c72015-11-20 16:39:34 -0700868VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR(
869 VkDevice device,
870 VkSwapchainKHR swapchain,
871 const VkAllocationCallbacks* pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600872{
873 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600874 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600875
876 // Validate that a valid VkDevice was used, and that the device
877 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600878 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600879 if (!pDevice) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700880 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600881 device,
882 "VkDevice");
883 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700884 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600885 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800886 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700887 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600888 }
889
890 // Regardless of skipCall value, do some internal cleanup:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600891 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600892 if (pSwapchain) {
893 // Delete the SwpSwapchain associated with this swapchain:
894 if (pSwapchain->pDevice) {
Chia-I Wue2fc5522015-10-26 20:04:44 +0800895 pSwapchain->pDevice->swapchains.erase(swapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600896 if (device != pSwapchain->pDevice->device) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700897 LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600898 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600899 "%s() called with a different VkDevice than the "
900 "VkSwapchainKHR was created with.",
901 __FUNCTION__);
902 }
903 }
904 if (pSwapchain->imageCount) {
905 pSwapchain->images.clear();
906 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600907 my_data->swapchainMap.erase(swapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600908 } else {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700909 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
Chia-I Wue2fc5522015-10-26 20:04:44 +0800910 swapchain,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600911 "VkSwapchainKHR");
912 }
913
914 if (VK_FALSE == skipCall) {
915 // Call down the call chain:
Ian Elliott27d39c72015-11-20 16:39:34 -0700916 my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600917 }
Ian Elliott0b4d6242015-09-22 10:51:24 -0600918}
919
Chia-I Wu9ab61502015-11-06 06:42:02 +0800920VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pCount, VkImage* pSwapchainImages)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600921{
922 VkResult result = VK_SUCCESS;
923 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600924 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600925
926 // Validate that a valid VkDevice was used, and that the device
927 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600928 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600929 if (!pDevice) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700930 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600931 device,
932 "VkDevice");
933 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700934 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600935 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800936 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700937 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600938 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600939 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600940 if (!pSwapchain) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700941 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600942 swapchain.handle,
943 "VkSwapchainKHR");
944 }
945
946 if (VK_FALSE == skipCall) {
947 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600948 result = my_data->device_dispatch_table->GetSwapchainImagesKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600949 device, swapchain, pCount, pSwapchainImages);
950
Ian Elliott66463852015-09-28 11:24:53 -0600951// TBD: Should we validate that this function was called once with
952// pSwapchainImages set to NULL (and record pCount at that time), and then
953// called again with a non-NULL pSwapchainImages?
Ian Elliott0b4d6242015-09-22 10:51:24 -0600954 if ((result == VK_SUCCESS) && pSwapchain &&pSwapchainImages &&
955 pCount && (*pCount > 0)) {
956 // Record the images and their state:
957 if (pSwapchain) {
958 pSwapchain->imageCount = *pCount;
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600959 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600960 pSwapchain->images[i].image = pSwapchainImages[i];
961 pSwapchain->images[i].pSwapchain = pSwapchain;
962 pSwapchain->images[i].ownedByApp = false;
963 }
964 }
965 }
966
967 return result;
968 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700969 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600970}
971
Ian Elliott27d39c72015-11-20 16:39:34 -0700972VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR(
973 VkDevice device,
974 VkSwapchainKHR swapchain,
975 uint64_t timeout,
976 VkSemaphore semaphore,
977 VkFence fence,
978 uint32_t* pImageIndex)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600979{
980// TODO: Record/update the state of the swapchain, in case an error occurs
981// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
982 VkResult result = VK_SUCCESS;
983 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600984 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600985
986 // Validate that a valid VkDevice was used, and that the device
987 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600988 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600989 if (!pDevice) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700990 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600991 device,
992 "VkDevice");
993 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700994 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600995 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800996 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700997 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600998 }
999 // Validate that a valid VkSwapchainKHR was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -06001000 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001001 if (!pSwapchain) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001002 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
Chia-I Wue2fc5522015-10-26 20:04:44 +08001003 swapchain,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001004 "VkSwapchainKHR");
1005 } else {
1006 // Look to see if the application is trying to own too many images at
1007 // the same time (i.e. not leave any to display):
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -06001008 uint32_t imagesOwnedByApp = 0;
1009 for (uint32_t i = 0 ; i < pSwapchain->imageCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001010 if (pSwapchain->images[i].ownedByApp) {
1011 imagesOwnedByApp++;
1012 }
1013 }
1014 if (imagesOwnedByApp >= (pSwapchain->imageCount - 1)) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001015 skipCall |= LOG_PERF_WARNING(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
Ian Elliott4a994452015-09-24 18:33:16 -06001016 swapchain,
1017 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001018 SWAPCHAIN_APP_OWNS_TOO_MANY_IMAGES,
Ian Elliott4a994452015-09-24 18:33:16 -06001019 "%s() called when the application "
1020 "already owns all presentable images "
1021 "in this swapchain except for the "
1022 "image currently being displayed. "
1023 "This call to %s() cannot succeed "
1024 "unless another thread calls the "
1025 "vkQueuePresentKHR() function in "
1026 "order to release ownership of one of "
1027 "the presentable images of this "
1028 "swapchain.",
1029 __FUNCTION__, __FUNCTION__);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001030 }
1031 }
1032
1033 if (VK_FALSE == skipCall) {
1034 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -06001035 result = my_data->device_dispatch_table->AcquireNextImageKHR(
Ian Elliott27d39c72015-11-20 16:39:34 -07001036 device, swapchain, timeout, semaphore, fence, pImageIndex);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001037
1038 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) &&
1039 pSwapchain) {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001040 // Change the state of the image (now owned by the application):
1041 pSwapchain->images[*pImageIndex].ownedByApp = true;
1042 }
1043
1044 return result;
1045 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07001046 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001047}
1048
Ian Elliott27d39c72015-11-20 16:39:34 -07001049VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(
1050 VkQueue queue,
1051 const VkPresentInfoKHR* pPresentInfo)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001052{
1053// TODOs:
1054//
1055// - Ensure that the queue is active, and is one of the queueFamilyIndex's
1056// that was returned by a previuos query.
1057// - Record/update the state of the swapchain, in case an error occurs
1058// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
1059 VkResult result = VK_SUCCESS;
1060 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -06001061 layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001062
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -06001063 for (uint32_t i = 0; i < pPresentInfo->swapchainCount ; i++) {
Ian Elliott27d39c72015-11-20 16:39:34 -07001064 uint32_t index = pPresentInfo->pImageIndices[i];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001065 SwpSwapchain *pSwapchain =
Ian Elliott27d39c72015-11-20 16:39:34 -07001066 &my_data->swapchainMap[pPresentInfo->pSwapchains[i]];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001067 if (pSwapchain) {
1068 if (!pSwapchain->pDevice->deviceSwapchainExtensionEnabled) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001069 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001070 pSwapchain->pDevice, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001071 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -08001072 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -07001073 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001074 }
1075 if (index >= pSwapchain->imageCount) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001076 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -07001077 pPresentInfo->pSwapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001078 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001079 SWAPCHAIN_INDEX_TOO_LARGE,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001080 "%s() called for an index that is too "
1081 "large (i.e. %d). There are only %d "
1082 "images in this VkSwapchainKHR.\n",
1083 __FUNCTION__, index,
1084 pSwapchain->imageCount);
1085 } else {
1086 if (!pSwapchain->images[index].ownedByApp) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001087 skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -07001088 pPresentInfo->pSwapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001089 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001090 SWAPCHAIN_INDEX_NOT_IN_USE,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001091 "%s() returned an index (i.e. %d) "
1092 "for an image that is not owned by "
1093 "the application.",
1094 __FUNCTION__, index);
1095 }
1096 }
1097 } else {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001098 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
Ian Elliott27d39c72015-11-20 16:39:34 -07001099 pPresentInfo->pSwapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001100 "VkSwapchainKHR");
1101 }
1102 }
1103
1104 if (VK_FALSE == skipCall) {
1105 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -06001106 result = my_data->device_dispatch_table->QueuePresentKHR(queue,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001107 pPresentInfo);
1108
1109 if ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -06001110 for (uint32_t i = 0; i < pPresentInfo->swapchainCount ; i++) {
Ian Elliott27d39c72015-11-20 16:39:34 -07001111 int index = pPresentInfo->pImageIndices[i];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001112 SwpSwapchain *pSwapchain =
Ian Elliott27d39c72015-11-20 16:39:34 -07001113 &my_data->swapchainMap[pPresentInfo->pSwapchains[i]];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001114 if (pSwapchain) {
1115 // Change the state of the image (no longer owned by the
1116 // application):
1117 pSwapchain->images[index].ownedByApp = false;
1118 }
1119 }
1120 }
1121
1122 return result;
1123 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -07001124 return VK_ERROR_VALIDATION_FAILED_EXT;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001125}
1126
1127static inline PFN_vkVoidFunction layer_intercept_proc(const char *name)
1128{
1129 if (!name || name[0] != 'v' || name[1] != 'k')
1130 return NULL;
1131
1132 name += 2;
1133 if (!strcmp(name, "CreateInstance"))
1134 return (PFN_vkVoidFunction) vkCreateInstance;
1135 if (!strcmp(name, "DestroyInstance"))
1136 return (PFN_vkVoidFunction) vkDestroyInstance;
1137 if (!strcmp(name, "EnumeratePhysicalDevices"))
1138 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
1139 if (!strcmp(name, "CreateDevice"))
1140 return (PFN_vkVoidFunction) vkCreateDevice;
1141 if (!strcmp(name, "DestroyDevice"))
1142 return (PFN_vkVoidFunction) vkDestroyDevice;
1143
1144 return NULL;
1145}
1146static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name)
1147{
1148 if (!name || name[0] != 'v' || name[1] != 'k')
1149 return NULL;
1150
1151 name += 2;
1152 if (!strcmp(name, "CreateInstance"))
1153 return (PFN_vkVoidFunction) vkCreateInstance;
1154 if (!strcmp(name, "DestroyInstance"))
1155 return (PFN_vkVoidFunction) vkDestroyInstance;
1156 if (!strcmp(name, "EnumeratePhysicalDevices"))
1157 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
1158
1159 return NULL;
1160}
1161
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001162VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(
1163 VkInstance instance,
1164 const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
1165 const VkAllocationCallbacks* pAllocator,
1166 VkDebugReportCallbackEXT* pMsgCallback)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001167{
Tobin Ehlis711ff312015-10-29 12:58:13 -06001168 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001169 VkResult result = my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Ian Elliott68124ac2015-10-07 16:18:35 -06001170 if (VK_SUCCESS == result) {
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07001171 result = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback);
Ian Elliott68124ac2015-10-07 16:18:35 -06001172 }
1173 return result;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001174}
1175
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001176VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, const VkAllocationCallbacks *pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001177{
Ian Elliott68124ac2015-10-07 16:18:35 -06001178 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001179 my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -07001180 layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001181}
1182
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001183VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07001184 VkInstance instance,
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001185 VkDebugReportFlagsEXT flags,
1186 VkDebugReportObjectTypeEXT objType,
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07001187 uint64_t object,
1188 size_t location,
1189 int32_t msgCode,
1190 const char* pLayerPrefix,
1191 const char* pMsg)
1192{
1193 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001194 my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -07001195}
1196
Chia-I Wu9ab61502015-11-06 06:42:02 +08001197VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001198{
1199 PFN_vkVoidFunction addr;
1200 if (device == VK_NULL_HANDLE) {
1201 return NULL;
1202 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001203
Tobin Ehlis711ff312015-10-29 12:58:13 -06001204 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001205 /* loader uses this to force layer initialization; device object is wrapped */
1206 if (!strcmp("vkGetDeviceProcAddr", funcName)) {
Tobin Ehlis711ff312015-10-29 12:58:13 -06001207 VkBaseLayerObject* wrapped_dev = (VkBaseLayerObject*) device;
1208 my_data = get_my_data_ptr(get_dispatch_key(wrapped_dev->baseObject), layer_data_map);
1209 my_data->device_dispatch_table = new VkLayerDispatchTable;
1210 layer_initialize_dispatch_table(my_data->device_dispatch_table, wrapped_dev);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001211 return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
1212 }
1213
1214 addr = layer_intercept_proc(funcName);
1215 if (addr)
1216 return addr;
1217
Tobin Ehlis711ff312015-10-29 12:58:13 -06001218 my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1219 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
1220 if (my_data->deviceMap.size() != 0 &&
Mark Lobodzinski6c1cb5a2015-11-05 15:27:03 -07001221 my_data->deviceMap[device].deviceSwapchainExtensionEnabled)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001222 {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001223 if (!strcmp("vkCreateSwapchainKHR", funcName))
1224 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateSwapchainKHR);
1225 if (!strcmp("vkDestroySwapchainKHR", funcName))
1226 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySwapchainKHR);
1227 if (!strcmp("vkGetSwapchainImagesKHR", funcName))
1228 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSwapchainImagesKHR);
1229 if (!strcmp("vkAcquireNextImageKHR", funcName))
1230 return reinterpret_cast<PFN_vkVoidFunction>(vkAcquireNextImageKHR);
1231 if (!strcmp("vkQueuePresentKHR", funcName))
1232 return reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR);
1233 }
1234 {
1235 if (pDisp->GetDeviceProcAddr == NULL)
1236 return NULL;
1237 return pDisp->GetDeviceProcAddr(device, funcName);
1238 }
1239}
1240
Chia-I Wu9ab61502015-11-06 06:42:02 +08001241VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001242{
1243 PFN_vkVoidFunction addr;
1244 if (instance == VK_NULL_HANDLE) {
1245 return NULL;
1246 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001247
Tobin Ehlis711ff312015-10-29 12:58:13 -06001248 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001249 /* loader uses this to force layer initialization; instance object is wrapped */
1250 if (!strcmp("vkGetInstanceProcAddr", funcName)) {
Tobin Ehlis711ff312015-10-29 12:58:13 -06001251 VkBaseLayerObject* wrapped_inst = (VkBaseLayerObject*) instance;
1252 my_data = get_my_data_ptr(get_dispatch_key(wrapped_inst->baseObject), layer_data_map);
1253 my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
1254 layer_init_instance_dispatch_table(my_data->instance_dispatch_table, wrapped_inst);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001255 return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
1256 }
1257
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -07001258 if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
1259 return (PFN_vkVoidFunction) vkEnumerateInstanceLayerProperties;
1260 if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
1261 return (PFN_vkVoidFunction) vkEnumerateInstanceExtensionProperties;
1262
Ian Elliott0b4d6242015-09-22 10:51:24 -06001263 addr = layer_intercept_instance_proc(funcName);
1264 if (addr)
1265 return addr;
1266
Tobin Ehlis711ff312015-10-29 12:58:13 -06001267 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1268 VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
Ian Elliott68124ac2015-10-07 16:18:35 -06001269 addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
1270 if (addr) {
1271 return addr;
1272 }
1273
Tobin Ehlis711ff312015-10-29 12:58:13 -06001274 if (my_data->instanceMap.size() != 0 &&
1275 my_data->instanceMap[instance].swapchainExtensionEnabled)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001276 {
1277 if (!strcmp("vkGetPhysicalDeviceSurfaceSupportKHR", funcName))
1278 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceSupportKHR);
Ian Elliott27d39c72015-11-20 16:39:34 -07001279 if (!strcmp("vkGetPhysicalDeviceSurfaceCapabilitiesKHR", funcName))
1280 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
1281 if (!strcmp("vkGetPhysicalDeviceSurfaceFormatsKHR", funcName))
1282 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceFormatsKHR);
1283 if (!strcmp("vkGetPhysicalDeviceSurfacePresentModesKHR", funcName))
1284 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfacePresentModesKHR);
1285// FIXME: ADD SUPPORT FOR THE vkCreate*SurfaceKHR() functions
Ian Elliott0b4d6242015-09-22 10:51:24 -06001286 }
1287
1288 if (pTable->GetInstanceProcAddr == NULL)
1289 return NULL;
1290 return pTable->GetInstanceProcAddr(instance, funcName);
1291}
1292