blob: 8a62f79a80e969bc90b2b931d61dff0ea4214b27 [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>
Ian Elliott0b4d6242015-09-22 10:51:24 -060029#include "swapchain.h"
Tobin Ehlis711ff312015-10-29 12:58:13 -060030#include "vk_layer_extension_utils.h"
Ian Elliott68124ac2015-10-07 16:18:35 -060031
Ian Elliott0b4d6242015-09-22 10:51:24 -060032// FIXME/TODO: Make sure this layer is thread-safe!
33
Ian Elliott68124ac2015-10-07 16:18:35 -060034
Ian Elliott0b4d6242015-09-22 10:51:24 -060035// The following is for logging error messages:
Ian Elliott68124ac2015-10-07 16:18:35 -060036static std::unordered_map<void *, layer_data *> layer_data_map;
Ian Elliott0b4d6242015-09-22 10:51:24 -060037
Ian Elliott68124ac2015-10-07 16:18:35 -060038template layer_data *get_my_data_ptr<layer_data>(
39 void *data_key,
40 std::unordered_map<void *, layer_data *> &data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -060041
Ian Elliott0b4d6242015-09-22 10:51:24 -060042
Ian Elliott0b4d6242015-09-22 10:51:24 -060043static void createDeviceRegisterExtensions(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, VkDevice device)
44{
45 uint32_t i;
Tobin Ehlis711ff312015-10-29 12:58:13 -060046 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
47 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
Ian Elliott0b4d6242015-09-22 10:51:24 -060048 PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr;
Ian Elliott1dcd1092015-11-17 17:29:40 -070049 pDisp->GetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR) gpa(device, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
50 pDisp->GetPhysicalDeviceSurfaceFormatsKHR = (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR) gpa(device, "vkGetPhysicalDeviceSurfaceFormatsKHR");
51 pDisp->GetPhysicalDeviceSurfacePresentModesKHR = (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR) gpa(device, "vkGetPhysicalDeviceSurfacePresentModesKHR");
Ian Elliott0b4d6242015-09-22 10:51:24 -060052 pDisp->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR) gpa(device, "vkCreateSwapchainKHR");
53 pDisp->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR) gpa(device, "vkDestroySwapchainKHR");
54 pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR) gpa(device, "vkGetSwapchainImagesKHR");
55 pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR) gpa(device, "vkAcquireNextImageKHR");
56 pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR) gpa(device, "vkQueuePresentKHR");
57
Tobin Ehlis711ff312015-10-29 12:58:13 -060058 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -060059 if (pPhysicalDevice) {
Tobin Ehlis711ff312015-10-29 12:58:13 -060060 my_data->deviceMap[device].pPhysicalDevice = pPhysicalDevice;
61 pPhysicalDevice->pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -060062 } else {
Ian Elliott68124ac2015-10-07 16:18:35 -060063 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -060064 LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_PHYSICAL_DEVICE,
65 physicalDevice,
66 "VkPhysicalDevice");
67 }
Tobin Ehlis711ff312015-10-29 12:58:13 -060068 my_data->deviceMap[device].device = device;
69 my_data->deviceMap[device].deviceSwapchainExtensionEnabled = false;
70 my_data->deviceMap[device].gotSurfaceProperties = false;
71 my_data->deviceMap[device].surfaceFormatCount = 0;
72 my_data->deviceMap[device].pSurfaceFormats = NULL;
73 my_data->deviceMap[device].presentModeCount = 0;
74 my_data->deviceMap[device].pPresentModes = NULL;
Ian Elliott0b4d6242015-09-22 10:51:24 -060075
76 // Record whether the WSI device extension was enabled for this VkDevice.
77 // No need to check if the extension was advertised by
78 // vkEnumerateDeviceExtensionProperties(), since the loader handles that.
Chia-I Wud50a7d72015-10-26 20:48:51 +080079 for (i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Ian Elliott1dcd1092015-11-17 17:29:40 -070080 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
Ian Elliott0b4d6242015-09-22 10:51:24 -060081
Tobin Ehlis711ff312015-10-29 12:58:13 -060082 my_data->deviceMap[device].deviceSwapchainExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -060083 }
84 }
85}
86
87static void createInstanceRegisterExtensions(const VkInstanceCreateInfo* pCreateInfo, VkInstance instance)
88{
89 uint32_t i;
Tobin Ehlis711ff312015-10-29 12:58:13 -060090 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
91 VkLayerInstanceDispatchTable *pDisp = my_data->instance_dispatch_table;
Ian Elliott0b4d6242015-09-22 10:51:24 -060092 PFN_vkGetInstanceProcAddr gpa = pDisp->GetInstanceProcAddr;
93 pDisp->GetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceSupportKHR");
94
Ian Elliott1dcd1092015-11-17 17:29:40 -070095 // Remember this instance, and whether the VK_KHR_surface extension
Ian Elliott0b4d6242015-09-22 10:51:24 -060096 // was enabled for it:
Tobin Ehlis711ff312015-10-29 12:58:13 -060097 my_data->instanceMap[instance].instance = instance;
98 my_data->instanceMap[instance].swapchainExtensionEnabled = false;
Ian Elliott0b4d6242015-09-22 10:51:24 -060099
100 // Record whether the WSI instance extension was enabled for this
101 // VkInstance. No need to check if the extension was advertised by
102 // vkEnumerateInstanceExtensionProperties(), since the loader handles that.
Chia-I Wud50a7d72015-10-26 20:48:51 +0800103 for (i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Ian Elliott1dcd1092015-11-17 17:29:40 -0700104 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600105
Tobin Ehlis711ff312015-10-29 12:58:13 -0600106 my_data->instanceMap[instance].swapchainExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600107 }
108 }
109}
110
111
112#include "vk_dispatch_table_helper.h"
Ian Elliott68124ac2015-10-07 16:18:35 -0600113static void initSwapchain(layer_data *my_data)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600114{
115 uint32_t report_flags = 0;
116 uint32_t debug_action = 0;
117 FILE *log_output = NULL;
118 const char *option_str;
Courtney Goeltzenleuchtercf60e0a2015-10-08 17:07:25 -0600119 VkDbgMsgCallback callback;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600120
121 // Initialize Swapchain options:
122 report_flags = getLayerOptionFlags("SwapchainReportFlags", 0);
123 getLayerOptionEnum("SwapchainDebugAction", (uint32_t *) &debug_action);
124
125 if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)
126 {
127 // Turn on logging, since it was requested:
128 option_str = getLayerOption("SwapchainLogFilename");
129 log_output = getLayerLogOutput(option_str, "Swapchain");
Ian Elliott68124ac2015-10-07 16:18:35 -0600130 layer_create_msg_callback(my_data->report_data, report_flags,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600131 log_callback, (void *) log_output,
Courtney Goeltzenleuchtercf60e0a2015-10-08 17:07:25 -0600132 &callback);
133 my_data->logging_callback.push_back(callback);
134 }
135 if (debug_action & VK_DBG_LAYER_ACTION_DEBUG_OUTPUT) {
136 layer_create_msg_callback(my_data->report_data, report_flags, win32_debug_output_msg, NULL, &callback);
137 my_data->logging_callback.push_back(callback);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600138 }
139}
140
141static const char *surfaceTransformStr(VkSurfaceTransformKHR value)
142{
143 static std::string surfaceTransformStrings[] = {
144 "VK_SURFACE_TRANSFORM_NONE_KHR",
145 "VK_SURFACE_TRANSFORM_ROT90_KHR",
146 "VK_SURFACE_TRANSFORM_ROT180_KHR",
147 "VK_SURFACE_TRANSFORM_ROT270_KHR",
148 "VK_SURFACE_TRANSFORM_HMIRROR_KHR",
149 "VK_SURFACE_TRANSFORM_HMIRROR_ROT90_KHR",
150 "VK_SURFACE_TRANSFORM_HMIRROR_ROT180_KHR",
151 "VK_SURFACE_TRANSFORM_HMIRROR_ROT270_KHR",
152 "Out-of-Range Value"};
153
154 // Deal with a out-of-range value:
155 switch (value) {
156 case VK_SURFACE_TRANSFORM_NONE_KHR:
157 case VK_SURFACE_TRANSFORM_ROT90_KHR:
158 case VK_SURFACE_TRANSFORM_ROT180_KHR:
159 case VK_SURFACE_TRANSFORM_ROT270_KHR:
160 case VK_SURFACE_TRANSFORM_HMIRROR_KHR:
161 case VK_SURFACE_TRANSFORM_HMIRROR_ROT90_KHR:
162 case VK_SURFACE_TRANSFORM_HMIRROR_ROT180_KHR:
163 case VK_SURFACE_TRANSFORM_HMIRROR_ROT270_KHR:
164 break;
165 default:
166 value =
167 (VkSurfaceTransformKHR) (VK_SURFACE_TRANSFORM_HMIRROR_ROT270_KHR + 1);
168 break;
169 }
170
171 // Return a string corresponding to the value:
172 return surfaceTransformStrings[value].c_str();
173}
174
175static const char *presentModeStr(VkPresentModeKHR value)
176{
177 static std::string presentModeStrings[] = {
178 "VK_PRESENT_MODE_IMMEDIATE_KHR",
179 "VK_PRESENT_MODE_MAILBOX_KHR",
180 "VK_PRESENT_MODE_FIFO_KHR",
181 "Out-of-Range Value"};
182
183 // Deal with a out-of-range value:
184 switch (value) {
185 case VK_PRESENT_MODE_IMMEDIATE_KHR:
186 case VK_PRESENT_MODE_MAILBOX_KHR:
187 case VK_PRESENT_MODE_FIFO_KHR:
188 break;
189 default:
190 value = (VkPresentModeKHR) (VK_PRESENT_MODE_FIFO_KHR + 1);
191 break;
192 }
193
194 // Return a string corresponding to the value:
195 return presentModeStrings[value].c_str();
196}
197
198
Chia-I Wu9ab61502015-11-06 06:42:02 +0800199VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600200{
Tobin Ehlis711ff312015-10-29 12:58:13 -0600201 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600202 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600203 VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
Chia-I Wuf7458c52015-10-26 21:10:41 +0800204 VkResult result = pTable->CreateInstance(pCreateInfo, pAllocator, pInstance);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600205 if (result == VK_SUCCESS) {
206 // Since it succeeded, do layer-specific work:
Ian Elliott68124ac2015-10-07 16:18:35 -0600207 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
208 my_data->report_data = debug_report_create_instance(
Tobin Ehlis711ff312015-10-29 12:58:13 -0600209 pTable,
Ian Elliott68124ac2015-10-07 16:18:35 -0600210 *pInstance,
Chia-I Wud50a7d72015-10-26 20:48:51 +0800211 pCreateInfo->enabledExtensionNameCount,
Ian Elliott68124ac2015-10-07 16:18:35 -0600212 pCreateInfo->ppEnabledExtensionNames);
213 // Call the following function after my_data is initialized:
Ian Elliott0b4d6242015-09-22 10:51:24 -0600214 createInstanceRegisterExtensions(pCreateInfo, *pInstance);
Ian Elliott68124ac2015-10-07 16:18:35 -0600215 initSwapchain(my_data);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600216 }
217 return result;
218}
219
Chia-I Wu9ab61502015-11-06 06:42:02 +0800220VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600221{
222 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600223 dispatch_key key = get_dispatch_key(instance);
224 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600225 // Validate that a valid VkInstance was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600226 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600227 if (!pInstance) {
228 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_INSTANCE,
229 instance,
230 "VkInstance");
231 }
232
233 if (VK_FALSE == skipCall) {
234 // Call down the call chain:
Chia-I Wuf7458c52015-10-26 21:10:41 +0800235 my_data->instance_dispatch_table->DestroyInstance(instance, pAllocator);
Ian Elliott68124ac2015-10-07 16:18:35 -0600236
237 // Clean up logging callback, if any
Courtney Goeltzenleuchtercf60e0a2015-10-08 17:07:25 -0600238 while (my_data->logging_callback.size() > 0) {
239 VkDbgMsgCallback callback = my_data->logging_callback.back();
240 layer_destroy_msg_callback(my_data->report_data, callback);
241 my_data->logging_callback.pop_back();
Ian Elliott68124ac2015-10-07 16:18:35 -0600242 }
243 layer_debug_report_destroy_instance(my_data->report_data);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600244 }
245
246 // Regardless of skipCall value, do some internal cleanup:
247 if (pInstance) {
248 // Delete all of the SwpPhysicalDevice's and the SwpInstance associated
249 // with this instance:
250 for (auto it = pInstance->physicalDevices.begin() ;
251 it != pInstance->physicalDevices.end() ; it++) {
Tobin Ehlis711ff312015-10-29 12:58:13 -0600252 // Erase the SwpPhysicalDevice's from the my_data->physicalDeviceMap (which
Ian Elliott0b4d6242015-09-22 10:51:24 -0600253 // are simply pointed to by the SwpInstance):
Tobin Ehlis711ff312015-10-29 12:58:13 -0600254 my_data->physicalDeviceMap.erase(it->second->physicalDevice);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600255 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600256 my_data->instanceMap.erase(instance);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600257 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600258 delete my_data->instance_dispatch_table;
259 layer_data_map.erase(key);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600260}
261
Chia-I Wu9ab61502015-11-06 06:42:02 +0800262VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600263{
264 VkResult result = VK_SUCCESS;
265 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600266 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600267
268 // Validate that a valid VkInstance was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600269 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600270 if (!pInstance) {
271 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_INSTANCE,
272 instance,
273 "VkInstance");
274 }
275
276 if (VK_FALSE == skipCall) {
277 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600278 result = my_data->instance_dispatch_table->EnumeratePhysicalDevices(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600279 instance, pPhysicalDeviceCount, pPhysicalDevices);
280
281 if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices &&
282 (*pPhysicalDeviceCount > 0)) {
283 // Record the VkPhysicalDevices returned by the ICD:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600284 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600285 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
Tobin Ehlis711ff312015-10-29 12:58:13 -0600286 my_data->physicalDeviceMap[pPhysicalDevices[i]].physicalDevice =
Ian Elliott0b4d6242015-09-22 10:51:24 -0600287 pPhysicalDevices[i];
Tobin Ehlis711ff312015-10-29 12:58:13 -0600288 my_data->physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance;
289 my_data->physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600290 // Point to the associated SwpInstance:
291 pInstance->physicalDevices[pPhysicalDevices[i]] =
Tobin Ehlis711ff312015-10-29 12:58:13 -0600292 &my_data->physicalDeviceMap[pPhysicalDevices[i]];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600293 }
294 }
295
296 return result;
297 }
298 return VK_ERROR_VALIDATION_FAILED;
299}
300
Chia-I Wu9ab61502015-11-06 06:42:02 +0800301VK_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 -0600302{
303 VkResult result = VK_SUCCESS;
304 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600305 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600306
307 // Validate that a valid VkPhysicalDevice was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600308 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600309 if (!pPhysicalDevice) {
310 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_PHYSICAL_DEVICE,
Mark Lobodzinski6c1cb5a2015-11-05 15:27:03 -0700311 physicalDevice, "VkPhysicalDevice");
Ian Elliott0b4d6242015-09-22 10:51:24 -0600312 }
313
Tobin Ehlis711ff312015-10-29 12:58:13 -0600314 if (VK_TRUE == skipCall)
315 return VK_ERROR_VALIDATION_FAILED;
316
317 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
318 // Call down the call chain:
319 result = my_device_data->device_dispatch_table->CreateDevice(
Chia-I Wuf7458c52015-10-26 21:10:41 +0800320 physicalDevice, pCreateInfo, pAllocator, pDevice);
Tobin Ehlis711ff312015-10-29 12:58:13 -0600321 if (result == VK_SUCCESS) {
322 // Since it succeeded, do layer-specific work:
Mark Lobodzinski6c1cb5a2015-11-05 15:27:03 -0700323 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
324 my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
325 createDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600326 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600327 return result;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600328}
329
Chia-I Wu9ab61502015-11-06 06:42:02 +0800330VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600331{
332 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600333 dispatch_key key = get_dispatch_key(device);
334 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600335 // Validate that a valid VkDevice was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600336 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600337 if (!pDevice) {
338 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
339 device,
340 "VkDevice");
341 }
342
343 if (VK_FALSE == skipCall) {
344 // Call down the call chain:
Chia-I Wuf7458c52015-10-26 21:10:41 +0800345 my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600346 }
347
348 // Regardless of skipCall value, do some internal cleanup:
349 if (pDevice) {
350 // Delete the SwpDevice associated with this device:
351 if (pDevice->pPhysicalDevice) {
352 pDevice->pPhysicalDevice->pDevice = NULL;
353 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600354 if (my_data->deviceMap[device].pSurfaceFormats) {
355 free(my_data->deviceMap[device].pSurfaceFormats);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600356 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600357 if (my_data->deviceMap[device].pPresentModes) {
358 free(my_data->deviceMap[device].pPresentModes);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600359 }
Ian Elliott0b4d6242015-09-22 10:51:24 -0600360 if (!pDevice->swapchains.empty()) {
361 LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600362 SWAPCHAIN_DEL_DEVICE_BEFORE_SWAPCHAINS,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600363 "%s() called before all of its associated "
364 "VkSwapchainKHRs were destroyed.",
365 __FUNCTION__);
366 // Empty and then delete all SwpSwapchain's
367 for (auto it = pDevice->swapchains.begin() ;
368 it != pDevice->swapchains.end() ; it++) {
369 // Delete all SwpImage's
370 it->second->images.clear();
371 }
372 pDevice->swapchains.clear();
373 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600374 my_data->deviceMap.erase(device);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600375 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600376 delete my_data->device_dispatch_table;
377 layer_data_map.erase(key);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600378}
379
Chia-I Wu9ab61502015-11-06 06:42:02 +0800380VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, const VkSurfaceDescriptionKHR* pSurfaceDescription, VkBool32* pSupported)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600381{
382 VkResult result = VK_SUCCESS;
383 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600384 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600385
386 // Validate that a valid VkPhysicalDevice was used, and that the instance
387 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600388 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600389 if (!pPhysicalDevice || !pPhysicalDevice->pInstance) {
390 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_PHYSICAL_DEVICE,
391 physicalDevice,
392 "VkPhysicalDevice");
393 } else if (!pPhysicalDevice->pInstance->swapchainExtensionEnabled) {
394 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_INSTANCE,
395 pPhysicalDevice->pInstance,
396 "VkInstance",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600397 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800398 "%s() called even though the %s extension was not enabled for this VkInstance.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700399 __FUNCTION__, VK_KHR_SURFACE_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600400 }
401
402 if (VK_FALSE == skipCall) {
403 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600404 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600405 physicalDevice, queueFamilyIndex, pSurfaceDescription,
406 pSupported);
407
408 if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
409 // Record the result of this query:
410 pPhysicalDevice->queueFamilyIndexSupport[queueFamilyIndex] =
411 *pSupported;
412 // TODO: We need to compare this with the actual queue used for
413 // presentation, to ensure it was advertised to the application as
414 // supported for presentation.
415 }
416
417 return result;
418 }
419 return VK_ERROR_VALIDATION_FAILED;
420}
421
Ian Elliott1dcd1092015-11-17 17:29:40 -0700422VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkDevice device, const VkSurfaceDescriptionKHR* pSurfaceDescription, VkSurfaceCapabilitiesKHR* pSurfaceProperties)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600423{
424 VkResult result = VK_SUCCESS;
425 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600426 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600427
428 // Validate that a valid VkDevice was used, and that the device
429 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600430 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600431 if (!pDevice) {
432 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
433 device,
434 "VkDevice");
435 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
436 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600437 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800438 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700439 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600440 }
441
442 if (VK_FALSE == skipCall) {
443 // Call down the call chain:
Ian Elliott1dcd1092015-11-17 17:29:40 -0700444 result = my_data->device_dispatch_table->GetPhysicalDeviceSurfaceCapabilitiesKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600445 device, pSurfaceDescription, pSurfaceProperties);
446
447 if ((result == VK_SUCCESS) && pDevice) {
448 pDevice->gotSurfaceProperties = true;
449 pDevice->surfaceProperties = *pSurfaceProperties;
450 }
451
452 return result;
453 }
454 return VK_ERROR_VALIDATION_FAILED;
455}
456
Ian Elliott1dcd1092015-11-17 17:29:40 -0700457VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR(VkDevice device, const VkSurfaceDescriptionKHR* pSurfaceDescription, uint32_t* pCount, VkSurfaceFormatKHR* pSurfaceFormats)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600458{
459 VkResult result = VK_SUCCESS;
460 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600461 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600462
463 // Validate that a valid VkDevice was used, and that the device
464 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600465 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600466 if (!pDevice) {
467 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
468 device,
469 "VkDevice");
470 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
471 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600472 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800473 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700474 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600475 }
476
477 if (VK_FALSE == skipCall) {
478 // Call down the call chain:
Ian Elliott1dcd1092015-11-17 17:29:40 -0700479 result = my_data->device_dispatch_table->GetPhysicalDeviceSurfaceFormatsKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600480 device, pSurfaceDescription, pCount, pSurfaceFormats);
481
482 if ((result == VK_SUCCESS) && pDevice && pSurfaceFormats && pCount &&
483 (*pCount > 0)) {
484 pDevice->surfaceFormatCount = *pCount;
485 pDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)
486 malloc(*pCount * sizeof(VkSurfaceFormatKHR));
487 if (pDevice->pSurfaceFormats) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600488 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600489 pDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
490 }
491 } else {
492 pDevice->surfaceFormatCount = 0;
493 }
494 }
495
496 return result;
497 }
498 return VK_ERROR_VALIDATION_FAILED;
499}
500
Ian Elliott1dcd1092015-11-17 17:29:40 -0700501VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR(VkDevice device, const VkSurfaceDescriptionKHR* pSurfaceDescription, uint32_t* pCount, VkPresentModeKHR* pPresentModes)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600502{
503 VkResult result = VK_SUCCESS;
504 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600505 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600506
507 // Validate that a valid VkDevice was used, and that the device
508 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600509 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600510 if (!pDevice) {
511 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
512 device,
513 "VkDevice");
514 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
515 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600516 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800517 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700518 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600519 }
520
521 if (VK_FALSE == skipCall) {
522 // Call down the call chain:
Ian Elliott1dcd1092015-11-17 17:29:40 -0700523 result = my_data->device_dispatch_table->GetPhysicalDeviceSurfacePresentModesKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600524 device, pSurfaceDescription, pCount, pPresentModes);
525
526 if ((result == VK_SUCCESS) && pDevice && pPresentModes && pCount &&
527 (*pCount > 0)) {
528 pDevice->presentModeCount = *pCount;
529 pDevice->pPresentModes = (VkPresentModeKHR *)
530 malloc(*pCount * sizeof(VkPresentModeKHR));
531 if (pDevice->pSurfaceFormats) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600532 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600533 pDevice->pPresentModes[i] = pPresentModes[i];
534 }
535 } else {
536 pDevice->presentModeCount = 0;
537 }
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:
574 if (!pDevice->gotSurfaceProperties) {
575 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:
583 VkSurfaceCapabilitiesKHR *pProps = &pDevice->surfaceProperties;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600584 if ((pCreateInfo->minImageCount < pProps->minImageCount) ||
585 ((pProps->maxImageCount > 0) &&
586 (pCreateInfo->minImageCount > pProps->maxImageCount))) {
587 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,
595 pProps->minImageCount,
596 pProps->maxImageCount);
597 }
598 // Validate pCreateInfo->imageExtent against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700599 // VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
Ian Elliott0b4d6242015-09-22 10:51:24 -0600600 if ((pProps->currentExtent.width == -1) &&
601 ((pCreateInfo->imageExtent.width < pProps->minImageExtent.width) ||
602 (pCreateInfo->imageExtent.width > pProps->maxImageExtent.width) ||
603 (pCreateInfo->imageExtent.height < pProps->minImageExtent.height) ||
604 (pCreateInfo->imageExtent.height > pProps->maxImageExtent.height))) {
605 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,
615 pProps->currentExtent.width,
616 pProps->currentExtent.height,
617 pProps->minImageExtent.width,
618 pProps->minImageExtent.height,
619 pProps->maxImageExtent.width,
620 pProps->maxImageExtent.height);
621 }
622 if ((pProps->currentExtent.width != -1) &&
623 ((pCreateInfo->imageExtent.width != pProps->currentExtent.width) ||
624 (pCreateInfo->imageExtent.height != pProps->currentExtent.height))) {
625 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,
634 pProps->currentExtent.width,
635 pProps->currentExtent.height);
636 }
637 // Validate pCreateInfo->preTransform against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700638 // VkSurfaceCapabilitiesKHR::supportedTransforms:
Ian Elliott0b4d6242015-09-22 10:51:24 -0600639 if (!((1 << pCreateInfo->preTransform) & pProps->supportedTransforms)) {
640 // 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;
652 for (int i = VK_SURFACE_TRANSFORM_NONE_KHR ;
653 i < VK_SURFACE_TRANSFORM_INHERIT_KHR ; i++) {
654 // Build up the rest of the message:
655 if ((1 << i) & pProps->supportedTransforms) {
656 const char *newStr =
657 surfaceTransformStr((VkSurfaceTransformKHR) (1 << i));
658 sprintf(str, " %s\n", newStr);
659 errorString += str;
660 }
661 }
662 // Log the message that we've built up:
Ian Elliott68124ac2015-10-07 16:18:35 -0600663 skipCall |= debug_report_log_msg(my_data->report_data,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600664 VK_DBG_REPORT_ERROR_BIT,
665 VK_OBJECT_TYPE_DEVICE,
Ian Elliottb0f474c2015-09-25 15:50:55 -0600666 (uint64_t) device, 0,
667 SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM,
668 LAYER_NAME,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600669 errorString.c_str());
670 }
671 // Validate pCreateInfo->imageArraySize against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700672 // VkSurfaceCapabilitiesKHR::maxImageArraySize:
Ian Elliott0b4d6242015-09-22 10:51:24 -0600673 if (pCreateInfo->imageArraySize <= pProps->maxImageArraySize) {
674 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600675 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_SIZE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600676 "%s() called with a non-supported "
677 "pCreateInfo->imageArraySize (i.e. %d). "
678 "Maximum value is %d.",
679 fn,
680 pCreateInfo->imageArraySize,
681 pProps->maxImageArraySize);
682 }
683 // Validate pCreateInfo->imageUsageFlags against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700684 // VkSurfaceCapabilitiesKHR::supportedUsageFlags:
Ian Elliott0b4d6242015-09-22 10:51:24 -0600685 if (pCreateInfo->imageUsageFlags &&
686 (pCreateInfo->imageUsageFlags !=
687 (pCreateInfo->imageUsageFlags & pProps->supportedUsageFlags))) {
688 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600689 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600690 "%s() called with a non-supported "
691 "pCreateInfo->imageUsageFlags (i.e. 0x%08x)."
692 " Supported flag bits are 0x%08x.",
693 fn,
694 pCreateInfo->imageUsageFlags,
695 pProps->supportedUsageFlags);
696 }
697 }
698 if (!pDevice->surfaceFormatCount) {
699 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600700 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600701 "%s() called before calling "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700702 "vkGetPhysicalDeviceSurfaceFormatsKHR().",
Ian Elliott0b4d6242015-09-22 10:51:24 -0600703 fn);
704 } else {
705 // Validate pCreateInfo->imageFormat against
706 // VkSurfaceFormatKHR::format:
707 bool foundFormat = false;
708 bool foundColorSpace = false;
709 bool foundMatch = false;
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600710 for (uint32_t i = 0 ; i < pDevice->surfaceFormatCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600711 if (pCreateInfo->imageFormat == pDevice->pSurfaceFormats[i].format) {
712 // Validate pCreateInfo->imageColorSpace against
713 // VkSurfaceFormatKHR::colorSpace:
714 foundFormat = true;
715 if (pCreateInfo->imageColorSpace == pDevice->pSurfaceFormats[i].colorSpace) {
716 foundMatch = true;
717 break;
718 }
719 } else {
720 if (pCreateInfo->imageColorSpace == pDevice->pSurfaceFormats[i].colorSpace) {
721 foundColorSpace = true;
722 }
723 }
724 }
725 if (!foundMatch) {
726 if (!foundFormat) {
727 if (!foundColorSpace) {
728 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device,
729 "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600730 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600731 "%s() called with neither a "
732 "supported pCreateInfo->imageFormat "
733 "(i.e. %d) nor a supported "
734 "pCreateInfo->imageColorSpace "
735 "(i.e. %d).",
736 fn,
737 pCreateInfo->imageFormat,
738 pCreateInfo->imageColorSpace);
739 } else {
740 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device,
Ian Elliottb0f474c2015-09-25 15:50:55 -0600741 "VkDevice",
742 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600743 "%s() called with a non-supported "
744 "pCreateInfo->imageFormat (i.e. %d).",
745 fn, pCreateInfo->imageFormat);
746 }
747 } else if (!foundColorSpace) {
748 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600749 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600750 "%s() called with a non-supported "
751 "pCreateInfo->imageColorSpace (i.e. %d).",
752 fn, pCreateInfo->imageColorSpace);
753 }
754 }
755 }
756 if (!pDevice->presentModeCount) {
757 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600758 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600759 "%s() called before calling "
Ian Elliott1dcd1092015-11-17 17:29:40 -0700760 "vkGetPhysicalDeviceSurfacePresentModesKHR().",
Ian Elliott0b4d6242015-09-22 10:51:24 -0600761 fn);
762 } else {
763 // Validate pCreateInfo->presentMode against
Ian Elliott1dcd1092015-11-17 17:29:40 -0700764 // vkGetPhysicalDeviceSurfacePresentModesKHR():
Ian Elliott0b4d6242015-09-22 10:51:24 -0600765 bool foundMatch = false;
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600766 for (uint32_t i = 0 ; i < pDevice->presentModeCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600767 if (pDevice->pPresentModes[i] == pCreateInfo->presentMode) {
768 foundMatch = true;
769 break;
770 }
771 }
772 if (!foundMatch) {
773 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600774 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600775 "%s() called with a non-supported "
776 "pCreateInfo->presentMode (i.e. %s).",
777 fn,
778 presentModeStr(pCreateInfo->presentMode));
779 }
780 }
781
782 // TODO: Validate the following values:
783 // - pCreateInfo->sharingMode
Chia-I Wud50a7d72015-10-26 20:48:51 +0800784 // - pCreateInfo->queueFamilyIndexCount
Ian Elliott0b4d6242015-09-22 10:51:24 -0600785 // - pCreateInfo->pQueueFamilyIndices
786 // - pCreateInfo->oldSwapchain
787
788 return skipCall;
789}
790
Chia-I Wu9ab61502015-11-06 06:42:02 +0800791VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, VkSwapchainKHR* pSwapchain)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600792{
793 VkResult result = VK_SUCCESS;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600794 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600795 VkBool32 skipCall = validateCreateSwapchainKHR(device, pCreateInfo,
796 pSwapchain);
797
798 if (VK_FALSE == skipCall) {
799 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600800 result = my_data->device_dispatch_table->CreateSwapchainKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600801 device, pCreateInfo, pSwapchain);
802
803 if (result == VK_SUCCESS) {
804 // Remember the swapchain's handle, and link it to the device:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600805 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600806
Tobin Ehlis711ff312015-10-29 12:58:13 -0600807 my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
Chia-I Wue2fc5522015-10-26 20:04:44 +0800808 pDevice->swapchains[*pSwapchain] =
Tobin Ehlis711ff312015-10-29 12:58:13 -0600809 &my_data->swapchainMap[*pSwapchain];
810 my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
811 my_data->swapchainMap[*pSwapchain].imageCount = 0;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600812 }
813
814 return result;
815 }
816 return VK_ERROR_VALIDATION_FAILED;
817}
818
Chia-I Wu9ab61502015-11-06 06:42:02 +0800819VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600820{
821 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600822 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600823
824 // Validate that a valid VkDevice was used, and that the device
825 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600826 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600827 if (!pDevice) {
828 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
829 device,
830 "VkDevice");
831 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
832 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600833 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800834 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700835 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600836 }
837
838 // Regardless of skipCall value, do some internal cleanup:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600839 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600840 if (pSwapchain) {
841 // Delete the SwpSwapchain associated with this swapchain:
842 if (pSwapchain->pDevice) {
Chia-I Wue2fc5522015-10-26 20:04:44 +0800843 pSwapchain->pDevice->swapchains.erase(swapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600844 if (device != pSwapchain->pDevice->device) {
845 LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600846 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600847 "%s() called with a different VkDevice than the "
848 "VkSwapchainKHR was created with.",
849 __FUNCTION__);
850 }
851 }
852 if (pSwapchain->imageCount) {
853 pSwapchain->images.clear();
854 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600855 my_data->swapchainMap.erase(swapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600856 } else {
857 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Chia-I Wue2fc5522015-10-26 20:04:44 +0800858 swapchain,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600859 "VkSwapchainKHR");
860 }
861
862 if (VK_FALSE == skipCall) {
863 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600864 VkResult result = my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600865 return result;
866 }
867 return VK_ERROR_VALIDATION_FAILED;
868}
869
Chia-I Wu9ab61502015-11-06 06:42:02 +0800870VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pCount, VkImage* pSwapchainImages)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600871{
872 VkResult result = VK_SUCCESS;
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) {
880 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
881 device,
882 "VkDevice");
883 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
884 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, 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 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600889 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600890 if (!pSwapchain) {
891 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
892 swapchain.handle,
893 "VkSwapchainKHR");
894 }
895
896 if (VK_FALSE == skipCall) {
897 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600898 result = my_data->device_dispatch_table->GetSwapchainImagesKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600899 device, swapchain, pCount, pSwapchainImages);
900
Ian Elliott66463852015-09-28 11:24:53 -0600901// TBD: Should we validate that this function was called once with
902// pSwapchainImages set to NULL (and record pCount at that time), and then
903// called again with a non-NULL pSwapchainImages?
Ian Elliott0b4d6242015-09-22 10:51:24 -0600904 if ((result == VK_SUCCESS) && pSwapchain &&pSwapchainImages &&
905 pCount && (*pCount > 0)) {
906 // Record the images and their state:
907 if (pSwapchain) {
908 pSwapchain->imageCount = *pCount;
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600909 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600910 pSwapchain->images[i].image = pSwapchainImages[i];
911 pSwapchain->images[i].pSwapchain = pSwapchain;
912 pSwapchain->images[i].ownedByApp = false;
913 }
914 }
915 }
916
917 return result;
918 }
919 return VK_ERROR_VALIDATION_FAILED;
920}
921
Chia-I Wu9ab61502015-11-06 06:42:02 +0800922VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, uint32_t* pImageIndex)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600923{
924// TODO: Record/update the state of the swapchain, in case an error occurs
925// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
926 VkResult result = VK_SUCCESS;
927 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600928 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600929
930 // Validate that a valid VkDevice was used, and that the device
931 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600932 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600933 if (!pDevice) {
934 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
935 device,
936 "VkDevice");
937 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
938 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600939 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -0800940 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -0700941 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600942 }
943 // Validate that a valid VkSwapchainKHR was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600944 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600945 if (!pSwapchain) {
946 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Chia-I Wue2fc5522015-10-26 20:04:44 +0800947 swapchain,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600948 "VkSwapchainKHR");
949 } else {
950 // Look to see if the application is trying to own too many images at
951 // the same time (i.e. not leave any to display):
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600952 uint32_t imagesOwnedByApp = 0;
953 for (uint32_t i = 0 ; i < pSwapchain->imageCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600954 if (pSwapchain->images[i].ownedByApp) {
955 imagesOwnedByApp++;
956 }
957 }
958 if (imagesOwnedByApp >= (pSwapchain->imageCount - 1)) {
Ian Elliott4a994452015-09-24 18:33:16 -0600959 skipCall |= LOG_PERF_WARNING(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
960 swapchain,
961 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600962 SWAPCHAIN_APP_OWNS_TOO_MANY_IMAGES,
Ian Elliott4a994452015-09-24 18:33:16 -0600963 "%s() called when the application "
964 "already owns all presentable images "
965 "in this swapchain except for the "
966 "image currently being displayed. "
967 "This call to %s() cannot succeed "
968 "unless another thread calls the "
969 "vkQueuePresentKHR() function in "
970 "order to release ownership of one of "
971 "the presentable images of this "
972 "swapchain.",
973 __FUNCTION__, __FUNCTION__);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600974 }
975 }
976
977 if (VK_FALSE == skipCall) {
978 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600979 result = my_data->device_dispatch_table->AcquireNextImageKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600980 device, swapchain, timeout, semaphore, pImageIndex);
981
982 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) &&
983 pSwapchain) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600984 // Change the state of the image (now owned by the application):
985 pSwapchain->images[*pImageIndex].ownedByApp = true;
986 }
987
988 return result;
989 }
990 return VK_ERROR_VALIDATION_FAILED;
991}
992
Chia-I Wu9ab61502015-11-06 06:42:02 +0800993VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(VkQueue queue, VkPresentInfoKHR* pPresentInfo)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600994{
995// TODOs:
996//
997// - Ensure that the queue is active, and is one of the queueFamilyIndex's
998// that was returned by a previuos query.
999// - Record/update the state of the swapchain, in case an error occurs
1000// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
1001 VkResult result = VK_SUCCESS;
1002 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -06001003 layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001004
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -06001005 for (uint32_t i = 0; i < pPresentInfo->swapchainCount ; i++) {
1006 uint32_t index = pPresentInfo->imageIndices[i];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001007 SwpSwapchain *pSwapchain =
Tobin Ehlis711ff312015-10-29 12:58:13 -06001008 &my_data->swapchainMap[pPresentInfo->swapchains[i]];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001009 if (pSwapchain) {
1010 if (!pSwapchain->pDevice->deviceSwapchainExtensionEnabled) {
1011 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE,
1012 pSwapchain->pDevice, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001013 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Michael Lentine010f4692015-11-03 16:19:46 -08001014 "%s() called even though the %s extension was not enabled for this VkDevice.",
Ian Elliott1dcd1092015-11-17 17:29:40 -07001015 __FUNCTION__, VK_KHR_SWAPCHAIN_EXTENSION_NAME);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001016 }
1017 if (index >= pSwapchain->imageCount) {
1018 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Chia-I Wue2fc5522015-10-26 20:04:44 +08001019 pPresentInfo->swapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001020 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001021 SWAPCHAIN_INDEX_TOO_LARGE,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001022 "%s() called for an index that is too "
1023 "large (i.e. %d). There are only %d "
1024 "images in this VkSwapchainKHR.\n",
1025 __FUNCTION__, index,
1026 pSwapchain->imageCount);
1027 } else {
1028 if (!pSwapchain->images[index].ownedByApp) {
1029 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Chia-I Wue2fc5522015-10-26 20:04:44 +08001030 pPresentInfo->swapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001031 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001032 SWAPCHAIN_INDEX_NOT_IN_USE,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001033 "%s() returned an index (i.e. %d) "
1034 "for an image that is not owned by "
1035 "the application.",
1036 __FUNCTION__, index);
1037 }
1038 }
1039 } else {
1040 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Chia-I Wue2fc5522015-10-26 20:04:44 +08001041 pPresentInfo->swapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001042 "VkSwapchainKHR");
1043 }
1044 }
1045
1046 if (VK_FALSE == skipCall) {
1047 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -06001048 result = my_data->device_dispatch_table->QueuePresentKHR(queue,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001049 pPresentInfo);
1050
1051 if ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -06001052 for (uint32_t i = 0; i < pPresentInfo->swapchainCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001053 int index = pPresentInfo->imageIndices[i];
1054 SwpSwapchain *pSwapchain =
Tobin Ehlis711ff312015-10-29 12:58:13 -06001055 &my_data->swapchainMap[pPresentInfo->swapchains[i]];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001056 if (pSwapchain) {
1057 // Change the state of the image (no longer owned by the
1058 // application):
1059 pSwapchain->images[index].ownedByApp = false;
1060 }
1061 }
1062 }
1063
1064 return result;
1065 }
1066 return VK_ERROR_VALIDATION_FAILED;
1067}
1068
1069static inline PFN_vkVoidFunction layer_intercept_proc(const char *name)
1070{
1071 if (!name || name[0] != 'v' || name[1] != 'k')
1072 return NULL;
1073
1074 name += 2;
1075 if (!strcmp(name, "CreateInstance"))
1076 return (PFN_vkVoidFunction) vkCreateInstance;
1077 if (!strcmp(name, "DestroyInstance"))
1078 return (PFN_vkVoidFunction) vkDestroyInstance;
1079 if (!strcmp(name, "EnumeratePhysicalDevices"))
1080 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
1081 if (!strcmp(name, "CreateDevice"))
1082 return (PFN_vkVoidFunction) vkCreateDevice;
1083 if (!strcmp(name, "DestroyDevice"))
1084 return (PFN_vkVoidFunction) vkDestroyDevice;
1085
1086 return NULL;
1087}
1088static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name)
1089{
1090 if (!name || name[0] != 'v' || name[1] != 'k')
1091 return NULL;
1092
1093 name += 2;
1094 if (!strcmp(name, "CreateInstance"))
1095 return (PFN_vkVoidFunction) vkCreateInstance;
1096 if (!strcmp(name, "DestroyInstance"))
1097 return (PFN_vkVoidFunction) vkDestroyInstance;
1098 if (!strcmp(name, "EnumeratePhysicalDevices"))
1099 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
1100
1101 return NULL;
1102}
1103
Chia-I Wu9ab61502015-11-06 06:42:02 +08001104VK_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 -06001105{
Tobin Ehlis711ff312015-10-29 12:58:13 -06001106 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1107 VkResult result = my_data->instance_dispatch_table->DbgCreateMsgCallback(instance, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
Ian Elliott68124ac2015-10-07 16:18:35 -06001108 if (VK_SUCCESS == result) {
Ian Elliott68124ac2015-10-07 16:18:35 -06001109 result = layer_create_msg_callback(my_data->report_data, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
1110 }
1111 return result;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001112}
1113
Chia-I Wu9ab61502015-11-06 06:42:02 +08001114VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkDbgDestroyMsgCallback(VkInstance instance, VkDbgMsgCallback msgCallback)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001115{
Ian Elliott68124ac2015-10-07 16:18:35 -06001116 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Tobin Ehlis711ff312015-10-29 12:58:13 -06001117 VkResult result = my_data->instance_dispatch_table->DbgDestroyMsgCallback(instance, msgCallback);
Ian Elliott68124ac2015-10-07 16:18:35 -06001118 layer_destroy_msg_callback(my_data->report_data, msgCallback);
1119 return result;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001120}
1121
Chia-I Wu9ab61502015-11-06 06:42:02 +08001122VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001123{
1124 PFN_vkVoidFunction addr;
1125 if (device == VK_NULL_HANDLE) {
1126 return NULL;
1127 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001128
Tobin Ehlis711ff312015-10-29 12:58:13 -06001129 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001130 /* loader uses this to force layer initialization; device object is wrapped */
1131 if (!strcmp("vkGetDeviceProcAddr", funcName)) {
Tobin Ehlis711ff312015-10-29 12:58:13 -06001132 VkBaseLayerObject* wrapped_dev = (VkBaseLayerObject*) device;
1133 my_data = get_my_data_ptr(get_dispatch_key(wrapped_dev->baseObject), layer_data_map);
1134 my_data->device_dispatch_table = new VkLayerDispatchTable;
1135 layer_initialize_dispatch_table(my_data->device_dispatch_table, wrapped_dev);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001136 return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
1137 }
1138
1139 addr = layer_intercept_proc(funcName);
1140 if (addr)
1141 return addr;
1142
Tobin Ehlis711ff312015-10-29 12:58:13 -06001143 my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1144 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
1145 if (my_data->deviceMap.size() != 0 &&
Mark Lobodzinski6c1cb5a2015-11-05 15:27:03 -07001146 my_data->deviceMap[device].deviceSwapchainExtensionEnabled)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001147 {
Ian Elliott1dcd1092015-11-17 17:29:40 -07001148 if (!strcmp("vkGetPhysicalDeviceSurfaceCapabilitiesKHR", funcName))
1149 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
1150 if (!strcmp("vkGetPhysicalDeviceSurfaceFormatsKHR", funcName))
1151 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceFormatsKHR);
1152 if (!strcmp("vkGetPhysicalDeviceSurfacePresentModesKHR", funcName))
1153 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfacePresentModesKHR);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001154 if (!strcmp("vkCreateSwapchainKHR", funcName))
1155 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateSwapchainKHR);
1156 if (!strcmp("vkDestroySwapchainKHR", funcName))
1157 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySwapchainKHR);
1158 if (!strcmp("vkGetSwapchainImagesKHR", funcName))
1159 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSwapchainImagesKHR);
1160 if (!strcmp("vkAcquireNextImageKHR", funcName))
1161 return reinterpret_cast<PFN_vkVoidFunction>(vkAcquireNextImageKHR);
1162 if (!strcmp("vkQueuePresentKHR", funcName))
1163 return reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR);
1164 }
1165 {
1166 if (pDisp->GetDeviceProcAddr == NULL)
1167 return NULL;
1168 return pDisp->GetDeviceProcAddr(device, funcName);
1169 }
1170}
1171
Chia-I Wu9ab61502015-11-06 06:42:02 +08001172VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001173{
1174 PFN_vkVoidFunction addr;
1175 if (instance == VK_NULL_HANDLE) {
1176 return NULL;
1177 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001178
Tobin Ehlis711ff312015-10-29 12:58:13 -06001179 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001180 /* loader uses this to force layer initialization; instance object is wrapped */
1181 if (!strcmp("vkGetInstanceProcAddr", funcName)) {
Tobin Ehlis711ff312015-10-29 12:58:13 -06001182 VkBaseLayerObject* wrapped_inst = (VkBaseLayerObject*) instance;
1183 my_data = get_my_data_ptr(get_dispatch_key(wrapped_inst->baseObject), layer_data_map);
1184 my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
1185 layer_init_instance_dispatch_table(my_data->instance_dispatch_table, wrapped_inst);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001186 return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
1187 }
1188
1189 addr = layer_intercept_instance_proc(funcName);
1190 if (addr)
1191 return addr;
1192
Tobin Ehlis711ff312015-10-29 12:58:13 -06001193 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1194 VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
Ian Elliott68124ac2015-10-07 16:18:35 -06001195 addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
1196 if (addr) {
1197 return addr;
1198 }
1199
Tobin Ehlis711ff312015-10-29 12:58:13 -06001200 if (my_data->instanceMap.size() != 0 &&
1201 my_data->instanceMap[instance].swapchainExtensionEnabled)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001202 {
1203 if (!strcmp("vkGetPhysicalDeviceSurfaceSupportKHR", funcName))
1204 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceSupportKHR);
1205 }
1206
1207 if (pTable->GetInstanceProcAddr == NULL)
1208 return NULL;
1209 return pTable->GetInstanceProcAddr(instance, funcName);
1210}
1211