blob: 72fb4f9823fd096d64cd09f2d0935881bcd0027c [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
Ian Elliott0b4d6242015-09-22 10:51:24 -060044
Ian Elliott0b4d6242015-09-22 10:51:24 -060045static void createDeviceRegisterExtensions(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, VkDevice device)
46{
47 uint32_t i;
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070048 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
49 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -060050
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070051 VkLayerDispatchTable *pDisp = my_device_data->device_dispatch_table;
52 PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr;
53
54 pDisp->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR) gpa(device, "vkCreateSwapchainKHR");
55 pDisp->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR) gpa(device, "vkDestroySwapchainKHR");
56 pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR) gpa(device, "vkGetSwapchainImagesKHR");
57 pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR) gpa(device, "vkAcquireNextImageKHR");
58 pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR) gpa(device, "vkQueuePresentKHR");
59
60 SwpPhysicalDevice *pPhysicalDevice = &my_instance_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -060061 if (pPhysicalDevice) {
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070062 my_device_data->deviceMap[device].pPhysicalDevice = pPhysicalDevice;
63 pPhysicalDevice->pDevice = &my_device_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -060064 } else {
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -070065 log_msg(my_instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_PHYSICAL_DEVICE,
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070066 (uint64_t)physicalDevice , 0, SWAPCHAIN_INVALID_HANDLE, "Swapchain",
67 "vkCreateDevice() called with a non-valid VkPhysicalDevice.");
Ian Elliott0b4d6242015-09-22 10:51:24 -060068 }
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070069 my_device_data->deviceMap[device].device = device;
70 my_device_data->deviceMap[device].deviceSwapchainExtensionEnabled = false;
Ian Elliott0b4d6242015-09-22 10:51:24 -060071
72 // Record whether the WSI device extension was enabled for this VkDevice.
73 // No need to check if the extension was advertised by
74 // vkEnumerateDeviceExtensionProperties(), since the loader handles that.
Chia-I Wud50a7d72015-10-26 20:48:51 +080075 for (i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Ian Elliott1dcd1092015-11-17 17:29:40 -070076 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
Ian Elliott0b4d6242015-09-22 10:51:24 -060077
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -070078 my_device_data->deviceMap[device].deviceSwapchainExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -060079 }
80 }
81}
82
83static void createInstanceRegisterExtensions(const VkInstanceCreateInfo* pCreateInfo, VkInstance instance)
84{
85 uint32_t i;
Tobin Ehlis711ff312015-10-29 12:58:13 -060086 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
87 VkLayerInstanceDispatchTable *pDisp = my_data->instance_dispatch_table;
Ian Elliott0b4d6242015-09-22 10:51:24 -060088 PFN_vkGetInstanceProcAddr gpa = pDisp->GetInstanceProcAddr;
89 pDisp->GetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceSupportKHR");
Ian Elliott27d39c72015-11-20 16:39:34 -070090 pDisp->GetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
91 pDisp->GetPhysicalDeviceSurfaceFormatsKHR = (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR");
92 pDisp->GetPhysicalDeviceSurfacePresentModesKHR = (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR) gpa(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR");
Ian Elliott0b4d6242015-09-22 10:51:24 -060093
Ian Elliott1dcd1092015-11-17 17:29:40 -070094 // Remember this instance, and whether the VK_KHR_surface extension
Ian Elliott0b4d6242015-09-22 10:51:24 -060095 // was enabled for it:
Tobin Ehlis711ff312015-10-29 12:58:13 -060096 my_data->instanceMap[instance].instance = instance;
97 my_data->instanceMap[instance].swapchainExtensionEnabled = false;
Ian Elliott0b4d6242015-09-22 10:51:24 -060098
99 // Record whether the WSI instance extension was enabled for this
100 // VkInstance. No need to check if the extension was advertised by
101 // vkEnumerateInstanceExtensionProperties(), since the loader handles that.
Chia-I Wud50a7d72015-10-26 20:48:51 +0800102 for (i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Ian Elliott1dcd1092015-11-17 17:29:40 -0700103 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600104
Tobin Ehlis711ff312015-10-29 12:58:13 -0600105 my_data->instanceMap[instance].swapchainExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600106 }
107 }
108}
109
110
111#include "vk_dispatch_table_helper.h"
Ian Elliott68124ac2015-10-07 16:18:35 -0600112static void initSwapchain(layer_data *my_data)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600113{
114 uint32_t report_flags = 0;
115 uint32_t debug_action = 0;
116 FILE *log_output = NULL;
117 const char *option_str;
Courtney Goeltzenleuchtercf60e0a2015-10-08 17:07:25 -0600118 VkDbgMsgCallback callback;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600119
120 // Initialize Swapchain options:
121 report_flags = getLayerOptionFlags("SwapchainReportFlags", 0);
122 getLayerOptionEnum("SwapchainDebugAction", (uint32_t *) &debug_action);
123
124 if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)
125 {
126 // Turn on logging, since it was requested:
127 option_str = getLayerOption("SwapchainLogFilename");
128 log_output = getLayerLogOutput(option_str, "Swapchain");
Ian Elliott68124ac2015-10-07 16:18:35 -0600129 layer_create_msg_callback(my_data->report_data, report_flags,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600130 log_callback, (void *) log_output,
Courtney Goeltzenleuchtercf60e0a2015-10-08 17:07:25 -0600131 &callback);
132 my_data->logging_callback.push_back(callback);
133 }
134 if (debug_action & VK_DBG_LAYER_ACTION_DEBUG_OUTPUT) {
135 layer_create_msg_callback(my_data->report_data, report_flags, win32_debug_output_msg, NULL, &callback);
136 my_data->logging_callback.push_back(callback);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600137 }
138}
139
Ian Elliott27d39c72015-11-20 16:39:34 -0700140static const char *surfaceTransformStr(VkSurfaceTransformFlagBitsKHR value)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600141{
Ian Elliott0b4d6242015-09-22 10:51:24 -0600142
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700143 // TODO: parse flags and print out one at a time
Ian Elliott0b4d6242015-09-22 10:51:24 -0600144 // Return a string corresponding to the value:
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700145 return string_VkSurfaceTransformFlagBitsKHR(value);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600146}
147
148static const char *presentModeStr(VkPresentModeKHR value)
149{
150 static std::string presentModeStrings[] = {
151 "VK_PRESENT_MODE_IMMEDIATE_KHR",
152 "VK_PRESENT_MODE_MAILBOX_KHR",
153 "VK_PRESENT_MODE_FIFO_KHR",
154 "Out-of-Range Value"};
155
156 // Deal with a out-of-range value:
157 switch (value) {
158 case VK_PRESENT_MODE_IMMEDIATE_KHR:
159 case VK_PRESENT_MODE_MAILBOX_KHR:
160 case VK_PRESENT_MODE_FIFO_KHR:
161 break;
162 default:
163 value = (VkPresentModeKHR) (VK_PRESENT_MODE_FIFO_KHR + 1);
164 break;
165 }
166
167 // Return a string corresponding to the value:
168 return presentModeStrings[value].c_str();
169}
170
171
Chia-I Wu9ab61502015-11-06 06:42:02 +0800172VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600173{
Tobin Ehlis711ff312015-10-29 12:58:13 -0600174 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600175 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600176 VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
Chia-I Wuf7458c52015-10-26 21:10:41 +0800177 VkResult result = pTable->CreateInstance(pCreateInfo, pAllocator, pInstance);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600178 if (result == VK_SUCCESS) {
179 // Since it succeeded, do layer-specific work:
Ian Elliott68124ac2015-10-07 16:18:35 -0600180 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
181 my_data->report_data = debug_report_create_instance(
Tobin Ehlis711ff312015-10-29 12:58:13 -0600182 pTable,
Ian Elliott68124ac2015-10-07 16:18:35 -0600183 *pInstance,
Chia-I Wud50a7d72015-10-26 20:48:51 +0800184 pCreateInfo->enabledExtensionNameCount,
Ian Elliott68124ac2015-10-07 16:18:35 -0600185 pCreateInfo->ppEnabledExtensionNames);
186 // Call the following function after my_data is initialized:
Ian Elliott0b4d6242015-09-22 10:51:24 -0600187 createInstanceRegisterExtensions(pCreateInfo, *pInstance);
Ian Elliott68124ac2015-10-07 16:18:35 -0600188 initSwapchain(my_data);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600189 }
190 return result;
191}
192
Chia-I Wu9ab61502015-11-06 06:42:02 +0800193VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600194{
195 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600196 dispatch_key key = get_dispatch_key(instance);
197 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600198 // Validate that a valid VkInstance was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600199 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600200 if (!pInstance) {
201 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_INSTANCE,
202 instance,
203 "VkInstance");
204 }
205
206 if (VK_FALSE == skipCall) {
207 // Call down the call chain:
Chia-I Wuf7458c52015-10-26 21:10:41 +0800208 my_data->instance_dispatch_table->DestroyInstance(instance, pAllocator);
Ian Elliott68124ac2015-10-07 16:18:35 -0600209
210 // Clean up logging callback, if any
Courtney Goeltzenleuchtercf60e0a2015-10-08 17:07:25 -0600211 while (my_data->logging_callback.size() > 0) {
212 VkDbgMsgCallback callback = my_data->logging_callback.back();
213 layer_destroy_msg_callback(my_data->report_data, callback);
214 my_data->logging_callback.pop_back();
Ian Elliott68124ac2015-10-07 16:18:35 -0600215 }
216 layer_debug_report_destroy_instance(my_data->report_data);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600217 }
218
219 // Regardless of skipCall value, do some internal cleanup:
220 if (pInstance) {
221 // Delete all of the SwpPhysicalDevice's and the SwpInstance associated
222 // with this instance:
223 for (auto it = pInstance->physicalDevices.begin() ;
224 it != pInstance->physicalDevices.end() ; it++) {
Ian Elliott27d39c72015-11-20 16:39:34 -0700225
226 // Free memory that was allocated for/by this SwpPhysicalDevice:
227 SwpPhysicalDevice *pPhysicalDevice = it->second;
228 free(pPhysicalDevice->pSurfaceFormats);
229 free(pPhysicalDevice->pPresentModes);
230
Tobin Ehlis711ff312015-10-29 12:58:13 -0600231 // Erase the SwpPhysicalDevice's from the my_data->physicalDeviceMap (which
Ian Elliott0b4d6242015-09-22 10:51:24 -0600232 // are simply pointed to by the SwpInstance):
Tobin Ehlis711ff312015-10-29 12:58:13 -0600233 my_data->physicalDeviceMap.erase(it->second->physicalDevice);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600234 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600235 my_data->instanceMap.erase(instance);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600236 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600237 delete my_data->instance_dispatch_table;
238 layer_data_map.erase(key);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600239}
240
Chia-I Wu9ab61502015-11-06 06:42:02 +0800241VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600242{
243 VkResult result = VK_SUCCESS;
244 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600245 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600246
247 // Validate that a valid VkInstance was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600248 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600249 if (!pInstance) {
250 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_INSTANCE,
251 instance,
252 "VkInstance");
253 }
254
255 if (VK_FALSE == skipCall) {
256 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600257 result = my_data->instance_dispatch_table->EnumeratePhysicalDevices(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600258 instance, pPhysicalDeviceCount, pPhysicalDevices);
259
260 if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices &&
261 (*pPhysicalDeviceCount > 0)) {
262 // Record the VkPhysicalDevices returned by the ICD:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600263 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600264 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
Tobin Ehlis711ff312015-10-29 12:58:13 -0600265 my_data->physicalDeviceMap[pPhysicalDevices[i]].physicalDevice =
Ian Elliott0b4d6242015-09-22 10:51:24 -0600266 pPhysicalDevices[i];
Tobin Ehlis711ff312015-10-29 12:58:13 -0600267 my_data->physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance;
268 my_data->physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL;
Ian Elliott27d39c72015-11-20 16:39:34 -0700269 my_data->physicalDeviceMap[pPhysicalDevices[i]].gotSurfaceCapabilities = false;
270 my_data->physicalDeviceMap[pPhysicalDevices[i]].surfaceFormatCount = 0;
271 my_data->physicalDeviceMap[pPhysicalDevices[i]].pSurfaceFormats = NULL;
272 my_data->physicalDeviceMap[pPhysicalDevices[i]].presentModeCount = 0;
273 my_data->physicalDeviceMap[pPhysicalDevices[i]].pPresentModes = NULL;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600274 // Point to the associated SwpInstance:
275 pInstance->physicalDevices[pPhysicalDevices[i]] =
Tobin Ehlis711ff312015-10-29 12:58:13 -0600276 &my_data->physicalDeviceMap[pPhysicalDevices[i]];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600277 }
278 }
279
280 return result;
281 }
282 return VK_ERROR_VALIDATION_FAILED;
283}
284
Chia-I Wu9ab61502015-11-06 06:42:02 +0800285VK_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 -0600286{
287 VkResult result = VK_SUCCESS;
288 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600289 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600290
291 // Validate that a valid VkPhysicalDevice was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600292 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600293 if (!pPhysicalDevice) {
294 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_PHYSICAL_DEVICE,
Mark Lobodzinski6c1cb5a2015-11-05 15:27:03 -0700295 physicalDevice, "VkPhysicalDevice");
Ian Elliott0b4d6242015-09-22 10:51:24 -0600296 }
297
Tobin Ehlis711ff312015-10-29 12:58:13 -0600298 if (VK_TRUE == skipCall)
299 return VK_ERROR_VALIDATION_FAILED;
300
301 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
302 // Call down the call chain:
303 result = my_device_data->device_dispatch_table->CreateDevice(
Chia-I Wuf7458c52015-10-26 21:10:41 +0800304 physicalDevice, pCreateInfo, pAllocator, pDevice);
Tobin Ehlis711ff312015-10-29 12:58:13 -0600305 if (result == VK_SUCCESS) {
306 // Since it succeeded, do layer-specific work:
Mark Lobodzinski6c1cb5a2015-11-05 15:27:03 -0700307 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
308 my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
309 createDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600310 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600311 return result;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600312}
313
Chia-I Wu9ab61502015-11-06 06:42:02 +0800314VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600315{
316 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600317 dispatch_key key = get_dispatch_key(device);
318 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600319 // Validate that a valid VkDevice was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600320 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600321 if (!pDevice) {
322 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
323 device,
324 "VkDevice");
325 }
326
327 if (VK_FALSE == skipCall) {
328 // Call down the call chain:
Chia-I Wuf7458c52015-10-26 21:10:41 +0800329 my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600330 }
331
332 // Regardless of skipCall value, do some internal cleanup:
333 if (pDevice) {
334 // Delete the SwpDevice associated with this device:
335 if (pDevice->pPhysicalDevice) {
336 pDevice->pPhysicalDevice->pDevice = NULL;
337 }
Ian Elliott0b4d6242015-09-22 10:51:24 -0600338 if (!pDevice->swapchains.empty()) {
339 LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600340 SWAPCHAIN_DEL_DEVICE_BEFORE_SWAPCHAINS,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600341 "%s() called before all of its associated "
342 "VkSwapchainKHRs were destroyed.",
343 __FUNCTION__);
344 // Empty and then delete all SwpSwapchain's
345 for (auto it = pDevice->swapchains.begin() ;
346 it != pDevice->swapchains.end() ; it++) {
347 // Delete all SwpImage's
348 it->second->images.clear();
349 }
350 pDevice->swapchains.clear();
351 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600352 my_data->deviceMap.erase(device);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600353 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600354 delete my_data->device_dispatch_table;
355 layer_data_map.erase(key);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600356}
357
Ian Elliott27d39c72015-11-20 16:39:34 -0700358VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(
359 VkPhysicalDevice physicalDevice,
360 uint32_t queueFamilyIndex,
361 VkSurfaceKHR surface,
362 VkBool32* pSupported)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600363{
364 VkResult result = VK_SUCCESS;
365 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600366 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600367
368 // Validate that a valid VkPhysicalDevice was used, and that the instance
369 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600370 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600371 if (!pPhysicalDevice || !pPhysicalDevice->pInstance) {
372 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_PHYSICAL_DEVICE,
373 physicalDevice,
374 "VkPhysicalDevice");
375 } else if (!pPhysicalDevice->pInstance->swapchainExtensionEnabled) {
376 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_INSTANCE,
377 pPhysicalDevice->pInstance,
378 "VkInstance",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600379 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800380 "%s() called even though the %s extension was not enabled for this VkInstance.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700381 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600382 }
383
384 if (VK_FALSE == skipCall) {
385 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600386 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(
Ian Elliott27d39c72015-11-20 16:39:34 -0700387 physicalDevice, queueFamilyIndex, surface,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600388 pSupported);
389
390 if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
391 // Record the result of this query:
392 pPhysicalDevice->queueFamilyIndexSupport[queueFamilyIndex] =
393 *pSupported;
394 // TODO: We need to compare this with the actual queue used for
395 // presentation, to ensure it was advertised to the application as
396 // supported for presentation.
397 }
398
399 return result;
400 }
401 return VK_ERROR_VALIDATION_FAILED;
402}
403
Ian Elliott27d39c72015-11-20 16:39:34 -0700404VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
405 VkPhysicalDevice physicalDevice,
406 VkSurfaceKHR surface,
407 VkSurfaceCapabilitiesKHR* pSurfaceCapabilities)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600408{
409 VkResult result = VK_SUCCESS;
410 VkBool32 skipCall = VK_FALSE;
Ian Elliott27d39c72015-11-20 16:39:34 -0700411 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600412
Ian Elliott27d39c72015-11-20 16:39:34 -0700413 // Validate that a valid VkPhysicalDevice was used, and that the instance
Ian Elliott0b4d6242015-09-22 10:51:24 -0600414 // extension was enabled:
Ian Elliott27d39c72015-11-20 16:39:34 -0700415 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
416 if (!pPhysicalDevice || !pPhysicalDevice->pInstance) {
417 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_PHYSICAL_DEVICE,
418 physicalDevice,
419 "VkPhysicalDevice");
420 } else if (!pPhysicalDevice->pInstance->swapchainExtensionEnabled) {
421 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_INSTANCE,
422 pPhysicalDevice->pInstance,
423 "VkInstance",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600424 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott27d39c72015-11-20 16:39:34 -0700425 "%s() called even though the %s extension was not enabled for this VkInstance.",
426 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600427 }
428
429 if (VK_FALSE == skipCall) {
430 // Call down the call chain:
Ian Elliott27d39c72015-11-20 16:39:34 -0700431 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceCapabilitiesKHR(
432 physicalDevice, surface, pSurfaceCapabilities);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600433
Ian Elliott27d39c72015-11-20 16:39:34 -0700434 if ((result == VK_SUCCESS) && pPhysicalDevice) {
435 pPhysicalDevice->gotSurfaceCapabilities = true;
436// FIXME: NEED TO COPY THIS DATA, BECAUSE pSurfaceCapabilities POINTS TO APP-ALLOCATED DATA
437 pPhysicalDevice->surfaceCapabilities = *pSurfaceCapabilities;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600438 }
439
440 return result;
441 }
442 return VK_ERROR_VALIDATION_FAILED;
443}
444
Ian Elliott27d39c72015-11-20 16:39:34 -0700445VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR(
446 VkPhysicalDevice physicalDevice,
447 VkSurfaceKHR surface,
448 uint32_t* pCount,
449 VkSurfaceFormatKHR* pSurfaceFormats)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600450{
451 VkResult result = VK_SUCCESS;
452 VkBool32 skipCall = VK_FALSE;
Ian Elliott27d39c72015-11-20 16:39:34 -0700453 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600454
Ian Elliott27d39c72015-11-20 16:39:34 -0700455 // Validate that a valid VkPhysicalDevice was used, and that the instance
Ian Elliott0b4d6242015-09-22 10:51:24 -0600456 // extension was enabled:
Ian Elliott27d39c72015-11-20 16:39:34 -0700457 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
458 if (!pPhysicalDevice || !pPhysicalDevice->pInstance) {
459 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_PHYSICAL_DEVICE,
460 physicalDevice,
461 "VkPhysicalDevice");
462 } else if (!pPhysicalDevice->pInstance->swapchainExtensionEnabled) {
463 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_INSTANCE,
464 pPhysicalDevice->pInstance,
465 "VkInstance",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600466 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott27d39c72015-11-20 16:39:34 -0700467 "%s() called even though the %s extension was not enabled for this VkInstance.",
468 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600469 }
470
471 if (VK_FALSE == skipCall) {
472 // Call down the call chain:
Ian Elliott27d39c72015-11-20 16:39:34 -0700473 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceFormatsKHR(
474 physicalDevice, surface, pCount, pSurfaceFormats);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600475
Ian Elliott27d39c72015-11-20 16:39:34 -0700476 if ((result == VK_SUCCESS) && pPhysicalDevice && pSurfaceFormats && pCount &&
Ian Elliott0b4d6242015-09-22 10:51:24 -0600477 (*pCount > 0)) {
Ian Elliott27d39c72015-11-20 16:39:34 -0700478 pPhysicalDevice->surfaceFormatCount = *pCount;
479 pPhysicalDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600480 malloc(*pCount * sizeof(VkSurfaceFormatKHR));
Ian Elliott27d39c72015-11-20 16:39:34 -0700481 if (pPhysicalDevice->pSurfaceFormats) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600482 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott27d39c72015-11-20 16:39:34 -0700483 pPhysicalDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600484 }
485 } else {
Ian Elliott27d39c72015-11-20 16:39:34 -0700486 pPhysicalDevice->surfaceFormatCount = 0;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600487 }
488 }
489
490 return result;
491 }
492 return VK_ERROR_VALIDATION_FAILED;
493}
494
Ian Elliott27d39c72015-11-20 16:39:34 -0700495VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR(
496 VkPhysicalDevice physicalDevice,
497 VkSurfaceKHR surface,
498 uint32_t* pCount,
499 VkPresentModeKHR* pPresentModes)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600500{
501 VkResult result = VK_SUCCESS;
502 VkBool32 skipCall = VK_FALSE;
Ian Elliott27d39c72015-11-20 16:39:34 -0700503 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600504
Ian Elliott27d39c72015-11-20 16:39:34 -0700505 // Validate that a valid VkPhysicalDevice was used, and that the instance
Ian Elliott0b4d6242015-09-22 10:51:24 -0600506 // extension was enabled:
Ian Elliott27d39c72015-11-20 16:39:34 -0700507 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
508 if (!pPhysicalDevice || !pPhysicalDevice->pInstance) {
509 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_PHYSICAL_DEVICE,
510 physicalDevice,
511 "VkPhysicalDevice");
512 } else if (!pPhysicalDevice->pInstance->swapchainExtensionEnabled) {
513 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_INSTANCE,
514 pPhysicalDevice->pInstance,
515 "VkInstance",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600516 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott27d39c72015-11-20 16:39:34 -0700517 "%s() called even though the %s extension was not enabled for this VkInstance.",
518 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600519 }
520
521 if (VK_FALSE == skipCall) {
522 // Call down the call chain:
Ian Elliott27d39c72015-11-20 16:39:34 -0700523 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfacePresentModesKHR(
524 physicalDevice, surface, pCount, pPresentModes);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600525
Ian Elliott27d39c72015-11-20 16:39:34 -0700526 if ((result == VK_SUCCESS) && pPhysicalDevice && pPresentModes && pCount &&
Ian Elliott0b4d6242015-09-22 10:51:24 -0600527 (*pCount > 0)) {
Ian Elliott27d39c72015-11-20 16:39:34 -0700528 pPhysicalDevice->presentModeCount = *pCount;
529 pPhysicalDevice->pPresentModes = (VkPresentModeKHR *)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600530 malloc(*pCount * sizeof(VkPresentModeKHR));
Ian Elliott27d39c72015-11-20 16:39:34 -0700531 if (pPhysicalDevice->pSurfaceFormats) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600532 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott27d39c72015-11-20 16:39:34 -0700533 pPhysicalDevice->pPresentModes[i] = pPresentModes[i];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600534 }
535 } else {
Ian Elliott27d39c72015-11-20 16:39:34 -0700536 pPhysicalDevice->presentModeCount = 0;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600537 }
538 }
539
540 return result;
541 }
542 return VK_ERROR_VALIDATION_FAILED;
543}
544
545// This function does the up-front validation work for vkCreateSwapchainKHR(),
546// and returns VK_TRUE if a logging callback indicates that the call down the
547// chain should be skipped:
548static VkBool32 validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, VkSwapchainKHR* pSwapchain)
549{
550// TODO: Validate cases of re-creating a swapchain (the current code
551// assumes a new swapchain is being created).
552 VkResult result = VK_SUCCESS;
553 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600554 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600555 char fn[] = "vkCreateSwapchainKHR";
556
557 // Validate that a valid VkDevice was used, and that the device
558 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600559 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600560 if (!pDevice) {
561 return LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600562 SWAPCHAIN_INVALID_HANDLE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600563 "%s() called with a non-valid %s.",
564 fn, "VkDevice");
565
566 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
567 return LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600568 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800569 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700570 fn, VK_KHR_SWAPCHAIN_EXTENSION_NAME );
Ian Elliott0b4d6242015-09-22 10:51:24 -0600571 }
572
573 // Validate pCreateInfo with the results for previous queries:
Ian Elliott27d39c72015-11-20 16:39:34 -0700574 if (!pDevice->pPhysicalDevice && !pDevice->pPhysicalDevice->gotSurfaceCapabilities) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600575 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600576 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600577 "%s() called before calling "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700578 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
Ian Elliott0b4d6242015-09-22 10:51:24 -0600579 fn);
580 } else {
581 // Validate pCreateInfo->minImageCount against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700582 // VkSurfaceCapabilitiesKHR::{min|max}ImageCount:
Ian Elliott27d39c72015-11-20 16:39:34 -0700583 VkSurfaceCapabilitiesKHR *pCapabilities = &pDevice->pPhysicalDevice->surfaceCapabilities;
584 if ((pCreateInfo->minImageCount < pCapabilities->minImageCount) ||
585 ((pCapabilities->maxImageCount > 0) &&
586 (pCreateInfo->minImageCount > pCapabilities->maxImageCount))) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600587 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600588 SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600589 "%s() called with pCreateInfo->minImageCount "
590 "= %d, which is outside the bounds returned "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700591 "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. "
Ian Elliott0b4d6242015-09-22 10:51:24 -0600592 "minImageCount = %d, maxImageCount = %d).",
593 fn,
594 pCreateInfo->minImageCount,
Ian Elliott27d39c72015-11-20 16:39:34 -0700595 pCapabilities->minImageCount,
596 pCapabilities->maxImageCount);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600597 }
598 // Validate pCreateInfo->imageExtent against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700599 // VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
Ian Elliott27d39c72015-11-20 16:39:34 -0700600 if ((pCapabilities->currentExtent.width == -1) &&
601 ((pCreateInfo->imageExtent.width < pCapabilities->minImageExtent.width) ||
602 (pCreateInfo->imageExtent.width > pCapabilities->maxImageExtent.width) ||
603 (pCreateInfo->imageExtent.height < pCapabilities->minImageExtent.height) ||
604 (pCreateInfo->imageExtent.height > pCapabilities->maxImageExtent.height))) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600605 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600606 SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600607 "%s() called with pCreateInfo->imageExtent = "
608 "(%d,%d), which is outside the bounds "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700609 "returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): "
Ian Elliott0b4d6242015-09-22 10:51:24 -0600610 "currentExtent = (%d,%d), minImageExtent = "
611 "(%d,%d), maxImageExtent = (%d,%d).",
612 fn,
613 pCreateInfo->imageExtent.width,
614 pCreateInfo->imageExtent.height,
Ian Elliott27d39c72015-11-20 16:39:34 -0700615 pCapabilities->currentExtent.width,
616 pCapabilities->currentExtent.height,
617 pCapabilities->minImageExtent.width,
618 pCapabilities->minImageExtent.height,
619 pCapabilities->maxImageExtent.width,
620 pCapabilities->maxImageExtent.height);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600621 }
Ian Elliott27d39c72015-11-20 16:39:34 -0700622 if ((pCapabilities->currentExtent.width != -1) &&
623 ((pCreateInfo->imageExtent.width != pCapabilities->currentExtent.width) ||
624 (pCreateInfo->imageExtent.height != pCapabilities->currentExtent.height))) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600625 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600626 SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600627 "%s() called with pCreateInfo->imageExtent = "
628 "(%d,%d), which is not equal to the "
629 "currentExtent = (%d,%d) returned by "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700630 "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
Ian Elliott0b4d6242015-09-22 10:51:24 -0600631 fn,
632 pCreateInfo->imageExtent.width,
633 pCreateInfo->imageExtent.height,
Ian Elliott27d39c72015-11-20 16:39:34 -0700634 pCapabilities->currentExtent.width,
635 pCapabilities->currentExtent.height);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600636 }
637 // Validate pCreateInfo->preTransform against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700638 // VkSurfaceCapabilitiesKHR::supportedTransforms:
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700639 if (!((pCreateInfo->preTransform) & pCapabilities->supportedTransforms)) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600640 // This is an error situation; one for which we'd like to give
641 // the developer a helpful, multi-line error message. Build it
642 // up a little at a time, and then log it:
643 std::string errorString = "";
644 char str[1024];
645 // Here's the first part of the message:
646 sprintf(str, "%s() called with a non-supported "
647 "pCreateInfo->preTransform (i.e. %s). "
648 "Supported values are:\n",
649 fn,
650 surfaceTransformStr(pCreateInfo->preTransform));
651 errorString += str;
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700652 for (int i = 0; i < 32; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600653 // Build up the rest of the message:
Ian Elliott27d39c72015-11-20 16:39:34 -0700654 if ((1 << i) & pCapabilities->supportedTransforms) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600655 const char *newStr =
Ian Elliott27d39c72015-11-20 16:39:34 -0700656 surfaceTransformStr((VkSurfaceTransformFlagBitsKHR) (1 << i));
Ian Elliott0b4d6242015-09-22 10:51:24 -0600657 sprintf(str, " %s\n", newStr);
658 errorString += str;
659 }
660 }
661 // Log the message that we've built up:
Ian Elliott68124ac2015-10-07 16:18:35 -0600662 skipCall |= debug_report_log_msg(my_data->report_data,
Courtney Goeltzenleuchterfd4830c2015-11-25 10:30:56 -0700663 VK_DEBUG_REPORT_ERROR_BIT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600664 VK_OBJECT_TYPE_DEVICE,
Mark Lobodzinski55cd49b2015-11-27 15:23:23 -0700665 (uint64_t) device, 0,
Ian Elliottb0f474c2015-09-25 15:50:55 -0600666 SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM,
667 LAYER_NAME,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600668 errorString.c_str());
669 }
670 // Validate pCreateInfo->imageArraySize against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700671 // VkSurfaceCapabilitiesKHR::maxImageArraySize:
Mark Lobodzinskia3b44522015-12-11 11:05:33 -0700672 if (pCreateInfo->imageArrayLayers > pCapabilities->maxImageArrayLayers) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600673 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600674 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_SIZE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600675 "%s() called with a non-supported "
676 "pCreateInfo->imageArraySize (i.e. %d). "
677 "Maximum value is %d.",
678 fn,
Ian Elliott27d39c72015-11-20 16:39:34 -0700679 pCreateInfo->imageArrayLayers,
680 pCapabilities->maxImageArrayLayers);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600681 }
Ian Elliott27d39c72015-11-20 16:39:34 -0700682 // Validate pCreateInfo->imageUsage against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700683 // VkSurfaceCapabilitiesKHR::supportedUsageFlags:
Ian Elliott27d39c72015-11-20 16:39:34 -0700684 if (pCreateInfo->imageUsage &&
685 (pCreateInfo->imageUsage !=
686 (pCreateInfo->imageUsage & pCapabilities->supportedUsageFlags))) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600687 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600688 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600689 "%s() called with a non-supported "
Ian Elliott27d39c72015-11-20 16:39:34 -0700690 "pCreateInfo->imageUsage (i.e. 0x%08x)."
Ian Elliott0b4d6242015-09-22 10:51:24 -0600691 " Supported flag bits are 0x%08x.",
692 fn,
Ian Elliott27d39c72015-11-20 16:39:34 -0700693 pCreateInfo->imageUsage,
694 pCapabilities->supportedUsageFlags);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600695 }
696 }
Ian Elliott27d39c72015-11-20 16:39:34 -0700697 if (!pDevice->pPhysicalDevice && !pDevice->pPhysicalDevice->surfaceFormatCount) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600698 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600699 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600700 "%s() called before calling "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700701 "vkGetPhysicalDeviceSurfaceFormatsKHR().",
Ian Elliott0b4d6242015-09-22 10:51:24 -0600702 fn);
703 } else {
704 // Validate pCreateInfo->imageFormat against
705 // VkSurfaceFormatKHR::format:
706 bool foundFormat = false;
707 bool foundColorSpace = false;
708 bool foundMatch = false;
Ian Elliott27d39c72015-11-20 16:39:34 -0700709 for (uint32_t i = 0 ; i < pDevice->pPhysicalDevice->surfaceFormatCount ; i++) {
710 if (pCreateInfo->imageFormat == pDevice->pPhysicalDevice->pSurfaceFormats[i].format) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600711 // Validate pCreateInfo->imageColorSpace against
712 // VkSurfaceFormatKHR::colorSpace:
713 foundFormat = true;
Ian Elliott27d39c72015-11-20 16:39:34 -0700714 if (pCreateInfo->imageColorSpace == pDevice->pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600715 foundMatch = true;
716 break;
717 }
718 } else {
Ian Elliott27d39c72015-11-20 16:39:34 -0700719 if (pCreateInfo->imageColorSpace == pDevice->pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600720 foundColorSpace = true;
721 }
722 }
723 }
724 if (!foundMatch) {
725 if (!foundFormat) {
726 if (!foundColorSpace) {
727 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device,
728 "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600729 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600730 "%s() called with neither a "
731 "supported pCreateInfo->imageFormat "
732 "(i.e. %d) nor a supported "
733 "pCreateInfo->imageColorSpace "
734 "(i.e. %d).",
735 fn,
736 pCreateInfo->imageFormat,
737 pCreateInfo->imageColorSpace);
738 } else {
739 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device,
Ian Elliottb0f474c2015-09-25 15:50:55 -0600740 "VkDevice",
741 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600742 "%s() called with a non-supported "
743 "pCreateInfo->imageFormat (i.e. %d).",
744 fn, pCreateInfo->imageFormat);
745 }
746 } else if (!foundColorSpace) {
747 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600748 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600749 "%s() called with a non-supported "
750 "pCreateInfo->imageColorSpace (i.e. %d).",
751 fn, pCreateInfo->imageColorSpace);
752 }
753 }
754 }
Ian Elliott27d39c72015-11-20 16:39:34 -0700755 if (!pDevice->pPhysicalDevice && !pDevice->pPhysicalDevice->presentModeCount) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600756 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600757 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600758 "%s() called before calling "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700759 "vkGetPhysicalDeviceSurfacePresentModesKHR().",
Ian Elliott0b4d6242015-09-22 10:51:24 -0600760 fn);
761 } else {
762 // Validate pCreateInfo->presentMode against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700763 // vkGetPhysicalDeviceSurfacePresentModesKHR():
Ian Elliott0b4d6242015-09-22 10:51:24 -0600764 bool foundMatch = false;
Ian Elliott27d39c72015-11-20 16:39:34 -0700765 for (uint32_t i = 0 ; i < pDevice->pPhysicalDevice->presentModeCount ; i++) {
766 if (pDevice->pPhysicalDevice->pPresentModes[i] == pCreateInfo->presentMode) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600767 foundMatch = true;
768 break;
769 }
770 }
771 if (!foundMatch) {
772 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600773 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600774 "%s() called with a non-supported "
775 "pCreateInfo->presentMode (i.e. %s).",
776 fn,
777 presentModeStr(pCreateInfo->presentMode));
778 }
779 }
780
781 // TODO: Validate the following values:
782 // - pCreateInfo->sharingMode
Chia-I Wud50a7d72015-10-26 20:48:51 +0800783 // - pCreateInfo->queueFamilyIndexCount
Ian Elliott0b4d6242015-09-22 10:51:24 -0600784 // - pCreateInfo->pQueueFamilyIndices
785 // - pCreateInfo->oldSwapchain
786
787 return skipCall;
788}
789
Ian Elliott27d39c72015-11-20 16:39:34 -0700790VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(
791 VkDevice device,
792 const VkSwapchainCreateInfoKHR* pCreateInfo,
793 const VkAllocationCallbacks* pAllocator,
794 VkSwapchainKHR* pSwapchain)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600795{
796 VkResult result = VK_SUCCESS;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600797 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600798 VkBool32 skipCall = validateCreateSwapchainKHR(device, pCreateInfo,
799 pSwapchain);
800
801 if (VK_FALSE == skipCall) {
802 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600803 result = my_data->device_dispatch_table->CreateSwapchainKHR(
Ian Elliott27d39c72015-11-20 16:39:34 -0700804 device, pCreateInfo, pAllocator, pSwapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600805
806 if (result == VK_SUCCESS) {
807 // Remember the swapchain's handle, and link it to the device:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600808 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600809
Tobin Ehlis711ff312015-10-29 12:58:13 -0600810 my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
Chia-I Wue2fc5522015-10-26 20:04:44 +0800811 pDevice->swapchains[*pSwapchain] =
Tobin Ehlis711ff312015-10-29 12:58:13 -0600812 &my_data->swapchainMap[*pSwapchain];
813 my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
814 my_data->swapchainMap[*pSwapchain].imageCount = 0;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600815 }
816
817 return result;
818 }
819 return VK_ERROR_VALIDATION_FAILED;
820}
821
Ian Elliott27d39c72015-11-20 16:39:34 -0700822VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR(
823 VkDevice device,
824 VkSwapchainKHR swapchain,
825 const VkAllocationCallbacks* pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600826{
827 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600828 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600829
830 // Validate that a valid VkDevice was used, and that the device
831 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600832 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600833 if (!pDevice) {
834 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
835 device,
836 "VkDevice");
837 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
838 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600839 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800840 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700841 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600842 }
843
844 // Regardless of skipCall value, do some internal cleanup:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600845 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600846 if (pSwapchain) {
847 // Delete the SwpSwapchain associated with this swapchain:
848 if (pSwapchain->pDevice) {
Chia-I Wue2fc5522015-10-26 20:04:44 +0800849 pSwapchain->pDevice->swapchains.erase(swapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600850 if (device != pSwapchain->pDevice->device) {
851 LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600852 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600853 "%s() called with a different VkDevice than the "
854 "VkSwapchainKHR was created with.",
855 __FUNCTION__);
856 }
857 }
858 if (pSwapchain->imageCount) {
859 pSwapchain->images.clear();
860 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600861 my_data->swapchainMap.erase(swapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600862 } else {
863 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Chia-I Wue2fc5522015-10-26 20:04:44 +0800864 swapchain,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600865 "VkSwapchainKHR");
866 }
867
868 if (VK_FALSE == skipCall) {
869 // Call down the call chain:
Ian Elliott27d39c72015-11-20 16:39:34 -0700870 my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600871 }
Ian Elliott0b4d6242015-09-22 10:51:24 -0600872}
873
Chia-I Wu9ab61502015-11-06 06:42:02 +0800874VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pCount, VkImage* pSwapchainImages)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600875{
876 VkResult result = VK_SUCCESS;
877 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600878 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600879
880 // Validate that a valid VkDevice was used, and that the device
881 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600882 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600883 if (!pDevice) {
884 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
885 device,
886 "VkDevice");
887 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
888 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600889 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800890 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700891 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600892 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600893 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600894 if (!pSwapchain) {
895 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
896 swapchain.handle,
897 "VkSwapchainKHR");
898 }
899
900 if (VK_FALSE == skipCall) {
901 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600902 result = my_data->device_dispatch_table->GetSwapchainImagesKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600903 device, swapchain, pCount, pSwapchainImages);
904
Ian Elliott66463852015-09-28 11:24:53 -0600905// TBD: Should we validate that this function was called once with
906// pSwapchainImages set to NULL (and record pCount at that time), and then
907// called again with a non-NULL pSwapchainImages?
Ian Elliott0b4d6242015-09-22 10:51:24 -0600908 if ((result == VK_SUCCESS) && pSwapchain &&pSwapchainImages &&
909 pCount && (*pCount > 0)) {
910 // Record the images and their state:
911 if (pSwapchain) {
912 pSwapchain->imageCount = *pCount;
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600913 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600914 pSwapchain->images[i].image = pSwapchainImages[i];
915 pSwapchain->images[i].pSwapchain = pSwapchain;
916 pSwapchain->images[i].ownedByApp = false;
917 }
918 }
919 }
920
921 return result;
922 }
923 return VK_ERROR_VALIDATION_FAILED;
924}
925
Ian Elliott27d39c72015-11-20 16:39:34 -0700926VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR(
927 VkDevice device,
928 VkSwapchainKHR swapchain,
929 uint64_t timeout,
930 VkSemaphore semaphore,
931 VkFence fence,
932 uint32_t* pImageIndex)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600933{
934// TODO: Record/update the state of the swapchain, in case an error occurs
935// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
936 VkResult result = VK_SUCCESS;
937 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600938 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600939
940 // Validate that a valid VkDevice was used, and that the device
941 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600942 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600943 if (!pDevice) {
944 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
945 device,
946 "VkDevice");
947 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
948 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600949 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800950 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700951 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600952 }
953 // Validate that a valid VkSwapchainKHR was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600954 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600955 if (!pSwapchain) {
956 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Chia-I Wue2fc5522015-10-26 20:04:44 +0800957 swapchain,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600958 "VkSwapchainKHR");
959 } else {
960 // Look to see if the application is trying to own too many images at
961 // the same time (i.e. not leave any to display):
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600962 uint32_t imagesOwnedByApp = 0;
963 for (uint32_t i = 0 ; i < pSwapchain->imageCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600964 if (pSwapchain->images[i].ownedByApp) {
965 imagesOwnedByApp++;
966 }
967 }
968 if (imagesOwnedByApp >= (pSwapchain->imageCount - 1)) {
Ian Elliott4a994452015-09-24 18:33:16 -0600969 skipCall |= LOG_PERF_WARNING(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
970 swapchain,
971 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600972 SWAPCHAIN_APP_OWNS_TOO_MANY_IMAGES,
Ian Elliott4a994452015-09-24 18:33:16 -0600973 "%s() called when the application "
974 "already owns all presentable images "
975 "in this swapchain except for the "
976 "image currently being displayed. "
977 "This call to %s() cannot succeed "
978 "unless another thread calls the "
979 "vkQueuePresentKHR() function in "
980 "order to release ownership of one of "
981 "the presentable images of this "
982 "swapchain.",
983 __FUNCTION__, __FUNCTION__);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600984 }
985 }
986
987 if (VK_FALSE == skipCall) {
988 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600989 result = my_data->device_dispatch_table->AcquireNextImageKHR(
Ian Elliott27d39c72015-11-20 16:39:34 -0700990 device, swapchain, timeout, semaphore, fence, pImageIndex);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600991
992 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) &&
993 pSwapchain) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600994 // Change the state of the image (now owned by the application):
995 pSwapchain->images[*pImageIndex].ownedByApp = true;
996 }
997
998 return result;
999 }
1000 return VK_ERROR_VALIDATION_FAILED;
1001}
1002
Ian Elliott27d39c72015-11-20 16:39:34 -07001003VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(
1004 VkQueue queue,
1005 const VkPresentInfoKHR* pPresentInfo)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001006{
1007// TODOs:
1008//
1009// - Ensure that the queue is active, and is one of the queueFamilyIndex's
1010// that was returned by a previuos query.
1011// - Record/update the state of the swapchain, in case an error occurs
1012// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
1013 VkResult result = VK_SUCCESS;
1014 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -06001015 layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001016
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -06001017 for (uint32_t i = 0; i < pPresentInfo->swapchainCount ; i++) {
Ian Elliott27d39c72015-11-20 16:39:34 -07001018 uint32_t index = pPresentInfo->pImageIndices[i];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001019 SwpSwapchain *pSwapchain =
Ian Elliott27d39c72015-11-20 16:39:34 -07001020 &my_data->swapchainMap[pPresentInfo->pSwapchains[i]];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001021 if (pSwapchain) {
1022 if (!pSwapchain->pDevice->deviceSwapchainExtensionEnabled) {
1023 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE,
1024 pSwapchain->pDevice, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001025 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -08001026 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -07001027 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001028 }
1029 if (index >= pSwapchain->imageCount) {
1030 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Ian Elliott27d39c72015-11-20 16:39:34 -07001031 pPresentInfo->pSwapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001032 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001033 SWAPCHAIN_INDEX_TOO_LARGE,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001034 "%s() called for an index that is too "
1035 "large (i.e. %d). There are only %d "
1036 "images in this VkSwapchainKHR.\n",
1037 __FUNCTION__, index,
1038 pSwapchain->imageCount);
1039 } else {
1040 if (!pSwapchain->images[index].ownedByApp) {
1041 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Ian Elliott27d39c72015-11-20 16:39:34 -07001042 pPresentInfo->pSwapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001043 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001044 SWAPCHAIN_INDEX_NOT_IN_USE,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001045 "%s() returned an index (i.e. %d) "
1046 "for an image that is not owned by "
1047 "the application.",
1048 __FUNCTION__, index);
1049 }
1050 }
1051 } else {
1052 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Ian Elliott27d39c72015-11-20 16:39:34 -07001053 pPresentInfo->pSwapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001054 "VkSwapchainKHR");
1055 }
1056 }
1057
1058 if (VK_FALSE == skipCall) {
1059 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -06001060 result = my_data->device_dispatch_table->QueuePresentKHR(queue,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001061 pPresentInfo);
1062
1063 if ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -06001064 for (uint32_t i = 0; i < pPresentInfo->swapchainCount ; i++) {
Ian Elliott27d39c72015-11-20 16:39:34 -07001065 int index = pPresentInfo->pImageIndices[i];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001066 SwpSwapchain *pSwapchain =
Ian Elliott27d39c72015-11-20 16:39:34 -07001067 &my_data->swapchainMap[pPresentInfo->pSwapchains[i]];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001068 if (pSwapchain) {
1069 // Change the state of the image (no longer owned by the
1070 // application):
1071 pSwapchain->images[index].ownedByApp = false;
1072 }
1073 }
1074 }
1075
1076 return result;
1077 }
1078 return VK_ERROR_VALIDATION_FAILED;
1079}
1080
1081static inline PFN_vkVoidFunction layer_intercept_proc(const char *name)
1082{
1083 if (!name || name[0] != 'v' || name[1] != 'k')
1084 return NULL;
1085
1086 name += 2;
1087 if (!strcmp(name, "CreateInstance"))
1088 return (PFN_vkVoidFunction) vkCreateInstance;
1089 if (!strcmp(name, "DestroyInstance"))
1090 return (PFN_vkVoidFunction) vkDestroyInstance;
1091 if (!strcmp(name, "EnumeratePhysicalDevices"))
1092 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
1093 if (!strcmp(name, "CreateDevice"))
1094 return (PFN_vkVoidFunction) vkCreateDevice;
1095 if (!strcmp(name, "DestroyDevice"))
1096 return (PFN_vkVoidFunction) vkDestroyDevice;
1097
1098 return NULL;
1099}
1100static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name)
1101{
1102 if (!name || name[0] != 'v' || name[1] != 'k')
1103 return NULL;
1104
1105 name += 2;
1106 if (!strcmp(name, "CreateInstance"))
1107 return (PFN_vkVoidFunction) vkCreateInstance;
1108 if (!strcmp(name, "DestroyInstance"))
1109 return (PFN_vkVoidFunction) vkDestroyInstance;
1110 if (!strcmp(name, "EnumeratePhysicalDevices"))
1111 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
1112
1113 return NULL;
1114}
1115
Chia-I Wu9ab61502015-11-06 06:42:02 +08001116VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkDbgCreateMsgCallback(VkInstance instance, VkFlags msgFlags, const PFN_vkDbgMsgCallback pfnMsgCallback, void* pUserData, VkDbgMsgCallback* pMsgCallback)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001117{
Tobin Ehlis711ff312015-10-29 12:58:13 -06001118 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1119 VkResult result = my_data->instance_dispatch_table->DbgCreateMsgCallback(instance, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
Ian Elliott68124ac2015-10-07 16:18:35 -06001120 if (VK_SUCCESS == result) {
Ian Elliott68124ac2015-10-07 16:18:35 -06001121 result = layer_create_msg_callback(my_data->report_data, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
1122 }
1123 return result;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001124}
1125
Chia-I Wu9ab61502015-11-06 06:42:02 +08001126VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkDbgDestroyMsgCallback(VkInstance instance, VkDbgMsgCallback msgCallback)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001127{
Ian Elliott68124ac2015-10-07 16:18:35 -06001128 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Tobin Ehlis711ff312015-10-29 12:58:13 -06001129 VkResult result = my_data->instance_dispatch_table->DbgDestroyMsgCallback(instance, msgCallback);
Ian Elliott68124ac2015-10-07 16:18:35 -06001130 layer_destroy_msg_callback(my_data->report_data, msgCallback);
1131 return result;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001132}
1133
Chia-I Wu9ab61502015-11-06 06:42:02 +08001134VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001135{
1136 PFN_vkVoidFunction addr;
1137 if (device == VK_NULL_HANDLE) {
1138 return NULL;
1139 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001140
Tobin Ehlis711ff312015-10-29 12:58:13 -06001141 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001142 /* loader uses this to force layer initialization; device object is wrapped */
1143 if (!strcmp("vkGetDeviceProcAddr", funcName)) {
Tobin Ehlis711ff312015-10-29 12:58:13 -06001144 VkBaseLayerObject* wrapped_dev = (VkBaseLayerObject*) device;
1145 my_data = get_my_data_ptr(get_dispatch_key(wrapped_dev->baseObject), layer_data_map);
1146 my_data->device_dispatch_table = new VkLayerDispatchTable;
1147 layer_initialize_dispatch_table(my_data->device_dispatch_table, wrapped_dev);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001148 return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
1149 }
1150
1151 addr = layer_intercept_proc(funcName);
1152 if (addr)
1153 return addr;
1154
Tobin Ehlis711ff312015-10-29 12:58:13 -06001155 my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1156 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
1157 if (my_data->deviceMap.size() != 0 &&
Mark Lobodzinski6c1cb5a2015-11-05 15:27:03 -07001158 my_data->deviceMap[device].deviceSwapchainExtensionEnabled)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001159 {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001160 if (!strcmp("vkCreateSwapchainKHR", funcName))
1161 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateSwapchainKHR);
1162 if (!strcmp("vkDestroySwapchainKHR", funcName))
1163 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySwapchainKHR);
1164 if (!strcmp("vkGetSwapchainImagesKHR", funcName))
1165 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSwapchainImagesKHR);
1166 if (!strcmp("vkAcquireNextImageKHR", funcName))
1167 return reinterpret_cast<PFN_vkVoidFunction>(vkAcquireNextImageKHR);
1168 if (!strcmp("vkQueuePresentKHR", funcName))
1169 return reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR);
1170 }
1171 {
1172 if (pDisp->GetDeviceProcAddr == NULL)
1173 return NULL;
1174 return pDisp->GetDeviceProcAddr(device, funcName);
1175 }
1176}
1177
Chia-I Wu9ab61502015-11-06 06:42:02 +08001178VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001179{
1180 PFN_vkVoidFunction addr;
1181 if (instance == VK_NULL_HANDLE) {
1182 return NULL;
1183 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001184
Tobin Ehlis711ff312015-10-29 12:58:13 -06001185 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001186 /* loader uses this to force layer initialization; instance object is wrapped */
1187 if (!strcmp("vkGetInstanceProcAddr", funcName)) {
Tobin Ehlis711ff312015-10-29 12:58:13 -06001188 VkBaseLayerObject* wrapped_inst = (VkBaseLayerObject*) instance;
1189 my_data = get_my_data_ptr(get_dispatch_key(wrapped_inst->baseObject), layer_data_map);
1190 my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
1191 layer_init_instance_dispatch_table(my_data->instance_dispatch_table, wrapped_inst);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001192 return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
1193 }
1194
1195 addr = layer_intercept_instance_proc(funcName);
1196 if (addr)
1197 return addr;
1198
Tobin Ehlis711ff312015-10-29 12:58:13 -06001199 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1200 VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
Ian Elliott68124ac2015-10-07 16:18:35 -06001201 addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
1202 if (addr) {
1203 return addr;
1204 }
1205
Tobin Ehlis711ff312015-10-29 12:58:13 -06001206 if (my_data->instanceMap.size() != 0 &&
1207 my_data->instanceMap[instance].swapchainExtensionEnabled)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001208 {
1209 if (!strcmp("vkGetPhysicalDeviceSurfaceSupportKHR", funcName))
1210 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceSupportKHR);
Ian Elliott27d39c72015-11-20 16:39:34 -07001211 if (!strcmp("vkGetPhysicalDeviceSurfaceCapabilitiesKHR", funcName))
1212 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
1213 if (!strcmp("vkGetPhysicalDeviceSurfaceFormatsKHR", funcName))
1214 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceFormatsKHR);
1215 if (!strcmp("vkGetPhysicalDeviceSurfacePresentModesKHR", funcName))
1216 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfacePresentModesKHR);
1217// FIXME: ADD SUPPORT FOR THE vkCreate*SurfaceKHR() functions
Ian Elliott0b4d6242015-09-22 10:51:24 -06001218 }
1219
1220 if (pTable->GetInstanceProcAddr == NULL)
1221 return NULL;
1222 return pTable->GetInstanceProcAddr(instance, funcName);
1223}
1224