blob: 37d04df14b4b174c4dc90ba2aaef030771c9a2a8 [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;
49 pDisp->GetSurfacePropertiesKHR = (PFN_vkGetSurfacePropertiesKHR) gpa(device, "vkGetSurfacePropertiesKHR");
50 pDisp->GetSurfaceFormatsKHR = (PFN_vkGetSurfaceFormatsKHR) gpa(device, "vkGetSurfaceFormatsKHR");
51 pDisp->GetSurfacePresentModesKHR = (PFN_vkGetSurfacePresentModesKHR) gpa(device, "vkGetSurfacePresentModesKHR");
52 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 Elliott0b4d6242015-09-22 10:51:24 -060080 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME) == 0) {
81
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
95 // Remember this instance, and whether the VK_EXT_KHR_swapchain extension
96 // 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 Elliott0b4d6242015-09-22 10:51:24 -0600104 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
105
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 Wu3432a0c2015-10-27 18:04:07 +0800199VK_LAYER_EXPORT VkResult VKAPI 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 Wu3432a0c2015-10-27 18:04:07 +0800220VK_LAYER_EXPORT void VKAPI 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
262VK_LAYER_EXPORT VkResult VKAPI vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices)
263{
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 Wu3432a0c2015-10-27 18:04:07 +0800301VK_LAYER_EXPORT VkResult VKAPI 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);
326
Ian Elliott0b4d6242015-09-22 10:51:24 -0600327 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600328 return result;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600329}
330
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800331VK_LAYER_EXPORT void VKAPI vkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600332{
333 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600334 dispatch_key key = get_dispatch_key(device);
335 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600336 // Validate that a valid VkDevice was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600337 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600338 if (!pDevice) {
339 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
340 device,
341 "VkDevice");
342 }
343
344 if (VK_FALSE == skipCall) {
345 // Call down the call chain:
Chia-I Wuf7458c52015-10-26 21:10:41 +0800346 my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600347 }
348
349 // Regardless of skipCall value, do some internal cleanup:
350 if (pDevice) {
351 // Delete the SwpDevice associated with this device:
352 if (pDevice->pPhysicalDevice) {
353 pDevice->pPhysicalDevice->pDevice = NULL;
354 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600355 if (my_data->deviceMap[device].pSurfaceFormats) {
356 free(my_data->deviceMap[device].pSurfaceFormats);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600357 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600358 if (my_data->deviceMap[device].pPresentModes) {
359 free(my_data->deviceMap[device].pPresentModes);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600360 }
Ian Elliott0b4d6242015-09-22 10:51:24 -0600361 if (!pDevice->swapchains.empty()) {
362 LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600363 SWAPCHAIN_DEL_DEVICE_BEFORE_SWAPCHAINS,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600364 "%s() called before all of its associated "
365 "VkSwapchainKHRs were destroyed.",
366 __FUNCTION__);
367 // Empty and then delete all SwpSwapchain's
368 for (auto it = pDevice->swapchains.begin() ;
369 it != pDevice->swapchains.end() ; it++) {
370 // Delete all SwpImage's
371 it->second->images.clear();
372 }
373 pDevice->swapchains.clear();
374 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600375 my_data->deviceMap.erase(device);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600376 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600377 delete my_data->device_dispatch_table;
378 layer_data_map.erase(key);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600379}
380
381VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, const VkSurfaceDescriptionKHR* pSurfaceDescription, VkBool32* pSupported)
382{
383 VkResult result = VK_SUCCESS;
384 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600385 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600386
387 // Validate that a valid VkPhysicalDevice was used, and that the instance
388 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600389 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600390 if (!pPhysicalDevice || !pPhysicalDevice->pInstance) {
391 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_PHYSICAL_DEVICE,
392 physicalDevice,
393 "VkPhysicalDevice");
394 } else if (!pPhysicalDevice->pInstance->swapchainExtensionEnabled) {
395 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_INSTANCE,
396 pPhysicalDevice->pInstance,
397 "VkInstance",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600398 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600399 "%s() called even though the "
400 VK_EXT_KHR_SWAPCHAIN_EXTENSION_NAME,
401 "extension was not enabled for this VkInstance.",
402 __FUNCTION__);
403 }
404
405 if (VK_FALSE == skipCall) {
406 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600407 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600408 physicalDevice, queueFamilyIndex, pSurfaceDescription,
409 pSupported);
410
411 if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
412 // Record the result of this query:
413 pPhysicalDevice->queueFamilyIndexSupport[queueFamilyIndex] =
414 *pSupported;
415 // TODO: We need to compare this with the actual queue used for
416 // presentation, to ensure it was advertised to the application as
417 // supported for presentation.
418 }
419
420 return result;
421 }
422 return VK_ERROR_VALIDATION_FAILED;
423}
424
425VK_LAYER_EXPORT VkResult VKAPI vkGetSurfacePropertiesKHR(VkDevice device, const VkSurfaceDescriptionKHR* pSurfaceDescription, VkSurfacePropertiesKHR* pSurfaceProperties)
426{
427 VkResult result = VK_SUCCESS;
428 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600429 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600430
431 // Validate that a valid VkDevice was used, and that the device
432 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600433 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600434 if (!pDevice) {
435 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
436 device,
437 "VkDevice");
438 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
439 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600440 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600441 "%s() called even though the "
442 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
443 "extension was not enabled for this VkDevice.",
444 __FUNCTION__);
445 }
446
447 if (VK_FALSE == skipCall) {
448 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600449 result = my_data->device_dispatch_table->GetSurfacePropertiesKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600450 device, pSurfaceDescription, pSurfaceProperties);
451
452 if ((result == VK_SUCCESS) && pDevice) {
453 pDevice->gotSurfaceProperties = true;
454 pDevice->surfaceProperties = *pSurfaceProperties;
455 }
456
457 return result;
458 }
459 return VK_ERROR_VALIDATION_FAILED;
460}
461
462VK_LAYER_EXPORT VkResult VKAPI vkGetSurfaceFormatsKHR(VkDevice device, const VkSurfaceDescriptionKHR* pSurfaceDescription, uint32_t* pCount, VkSurfaceFormatKHR* pSurfaceFormats)
463{
464 VkResult result = VK_SUCCESS;
465 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600466 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600467
468 // Validate that a valid VkDevice was used, and that the device
469 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600470 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600471 if (!pDevice) {
472 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
473 device,
474 "VkDevice");
475 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
476 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600477 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600478 "%s() called even though the "
479 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
480 "extension was not enabled for this VkDevice.",
481 __FUNCTION__);
482 }
483
484 if (VK_FALSE == skipCall) {
485 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600486 result = my_data->device_dispatch_table->GetSurfaceFormatsKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600487 device, pSurfaceDescription, pCount, pSurfaceFormats);
488
489 if ((result == VK_SUCCESS) && pDevice && pSurfaceFormats && pCount &&
490 (*pCount > 0)) {
491 pDevice->surfaceFormatCount = *pCount;
492 pDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)
493 malloc(*pCount * sizeof(VkSurfaceFormatKHR));
494 if (pDevice->pSurfaceFormats) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600495 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600496 pDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
497 }
498 } else {
499 pDevice->surfaceFormatCount = 0;
500 }
501 }
502
503 return result;
504 }
505 return VK_ERROR_VALIDATION_FAILED;
506}
507
508VK_LAYER_EXPORT VkResult VKAPI vkGetSurfacePresentModesKHR(VkDevice device, const VkSurfaceDescriptionKHR* pSurfaceDescription, uint32_t* pCount, VkPresentModeKHR* pPresentModes)
509{
510 VkResult result = VK_SUCCESS;
511 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600512 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600513
514 // Validate that a valid VkDevice was used, and that the device
515 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600516 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600517 if (!pDevice) {
518 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
519 device,
520 "VkDevice");
521 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
522 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600523 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600524 "%s() called even though the "
525 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
526 "extension was not enabled for this VkDevice.",
527 __FUNCTION__);
528 }
529
530 if (VK_FALSE == skipCall) {
531 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600532 result = my_data->device_dispatch_table->GetSurfacePresentModesKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600533 device, pSurfaceDescription, pCount, pPresentModes);
534
535 if ((result == VK_SUCCESS) && pDevice && pPresentModes && pCount &&
536 (*pCount > 0)) {
537 pDevice->presentModeCount = *pCount;
538 pDevice->pPresentModes = (VkPresentModeKHR *)
539 malloc(*pCount * sizeof(VkPresentModeKHR));
540 if (pDevice->pSurfaceFormats) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600541 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600542 pDevice->pPresentModes[i] = pPresentModes[i];
543 }
544 } else {
545 pDevice->presentModeCount = 0;
546 }
547 }
548
549 return result;
550 }
551 return VK_ERROR_VALIDATION_FAILED;
552}
553
554// This function does the up-front validation work for vkCreateSwapchainKHR(),
555// and returns VK_TRUE if a logging callback indicates that the call down the
556// chain should be skipped:
557static VkBool32 validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, VkSwapchainKHR* pSwapchain)
558{
559// TODO: Validate cases of re-creating a swapchain (the current code
560// assumes a new swapchain is being created).
561 VkResult result = VK_SUCCESS;
562 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600563 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600564 char fn[] = "vkCreateSwapchainKHR";
565
566 // Validate that a valid VkDevice was used, and that the device
567 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600568 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600569 if (!pDevice) {
570 return LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600571 SWAPCHAIN_INVALID_HANDLE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600572 "%s() called with a non-valid %s.",
573 fn, "VkDevice");
574
575 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
576 return LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600577 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600578 "%s() called even though the "
579 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
580 "extension was not enabled for this VkDevice.",
581 fn);
582 }
583
584 // Validate pCreateInfo with the results for previous queries:
585 if (!pDevice->gotSurfaceProperties) {
586 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600587 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600588 "%s() called before calling "
589 "vkGetSurfacePropertiesKHR().",
590 fn);
591 } else {
592 // Validate pCreateInfo->minImageCount against
593 // VkSurfacePropertiesKHR::{min|max}ImageCount:
594 VkSurfacePropertiesKHR *pProps = &pDevice->surfaceProperties;
595 if ((pCreateInfo->minImageCount < pProps->minImageCount) ||
596 ((pProps->maxImageCount > 0) &&
597 (pCreateInfo->minImageCount > pProps->maxImageCount))) {
598 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600599 SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600600 "%s() called with pCreateInfo->minImageCount "
601 "= %d, which is outside the bounds returned "
602 "by vkGetSurfacePropertiesKHR() (i.e. "
603 "minImageCount = %d, maxImageCount = %d).",
604 fn,
605 pCreateInfo->minImageCount,
606 pProps->minImageCount,
607 pProps->maxImageCount);
608 }
609 // Validate pCreateInfo->imageExtent against
610 // VkSurfacePropertiesKHR::{current|min|max}ImageExtent:
611 if ((pProps->currentExtent.width == -1) &&
612 ((pCreateInfo->imageExtent.width < pProps->minImageExtent.width) ||
613 (pCreateInfo->imageExtent.width > pProps->maxImageExtent.width) ||
614 (pCreateInfo->imageExtent.height < pProps->minImageExtent.height) ||
615 (pCreateInfo->imageExtent.height > pProps->maxImageExtent.height))) {
616 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600617 SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600618 "%s() called with pCreateInfo->imageExtent = "
619 "(%d,%d), which is outside the bounds "
620 "returned by vkGetSurfacePropertiesKHR(): "
621 "currentExtent = (%d,%d), minImageExtent = "
622 "(%d,%d), maxImageExtent = (%d,%d).",
623 fn,
624 pCreateInfo->imageExtent.width,
625 pCreateInfo->imageExtent.height,
626 pProps->currentExtent.width,
627 pProps->currentExtent.height,
628 pProps->minImageExtent.width,
629 pProps->minImageExtent.height,
630 pProps->maxImageExtent.width,
631 pProps->maxImageExtent.height);
632 }
633 if ((pProps->currentExtent.width != -1) &&
634 ((pCreateInfo->imageExtent.width != pProps->currentExtent.width) ||
635 (pCreateInfo->imageExtent.height != pProps->currentExtent.height))) {
636 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600637 SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600638 "%s() called with pCreateInfo->imageExtent = "
639 "(%d,%d), which is not equal to the "
640 "currentExtent = (%d,%d) returned by "
641 "vkGetSurfacePropertiesKHR().",
642 fn,
643 pCreateInfo->imageExtent.width,
644 pCreateInfo->imageExtent.height,
645 pProps->currentExtent.width,
646 pProps->currentExtent.height);
647 }
648 // Validate pCreateInfo->preTransform against
649 // VkSurfacePropertiesKHR::supportedTransforms:
650 if (!((1 << pCreateInfo->preTransform) & pProps->supportedTransforms)) {
651 // This is an error situation; one for which we'd like to give
652 // the developer a helpful, multi-line error message. Build it
653 // up a little at a time, and then log it:
654 std::string errorString = "";
655 char str[1024];
656 // Here's the first part of the message:
657 sprintf(str, "%s() called with a non-supported "
658 "pCreateInfo->preTransform (i.e. %s). "
659 "Supported values are:\n",
660 fn,
661 surfaceTransformStr(pCreateInfo->preTransform));
662 errorString += str;
663 for (int i = VK_SURFACE_TRANSFORM_NONE_KHR ;
664 i < VK_SURFACE_TRANSFORM_INHERIT_KHR ; i++) {
665 // Build up the rest of the message:
666 if ((1 << i) & pProps->supportedTransforms) {
667 const char *newStr =
668 surfaceTransformStr((VkSurfaceTransformKHR) (1 << i));
669 sprintf(str, " %s\n", newStr);
670 errorString += str;
671 }
672 }
673 // Log the message that we've built up:
Ian Elliott68124ac2015-10-07 16:18:35 -0600674 skipCall |= debug_report_log_msg(my_data->report_data,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600675 VK_DBG_REPORT_ERROR_BIT,
676 VK_OBJECT_TYPE_DEVICE,
Ian Elliottb0f474c2015-09-25 15:50:55 -0600677 (uint64_t) device, 0,
678 SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM,
679 LAYER_NAME,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600680 errorString.c_str());
681 }
682 // Validate pCreateInfo->imageArraySize against
683 // VkSurfacePropertiesKHR::maxImageArraySize:
684 if (pCreateInfo->imageArraySize <= pProps->maxImageArraySize) {
685 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600686 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_SIZE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600687 "%s() called with a non-supported "
688 "pCreateInfo->imageArraySize (i.e. %d). "
689 "Maximum value is %d.",
690 fn,
691 pCreateInfo->imageArraySize,
692 pProps->maxImageArraySize);
693 }
694 // Validate pCreateInfo->imageUsageFlags against
695 // VkSurfacePropertiesKHR::supportedUsageFlags:
696 if (pCreateInfo->imageUsageFlags &&
697 (pCreateInfo->imageUsageFlags !=
698 (pCreateInfo->imageUsageFlags & pProps->supportedUsageFlags))) {
699 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600700 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600701 "%s() called with a non-supported "
702 "pCreateInfo->imageUsageFlags (i.e. 0x%08x)."
703 " Supported flag bits are 0x%08x.",
704 fn,
705 pCreateInfo->imageUsageFlags,
706 pProps->supportedUsageFlags);
707 }
708 }
709 if (!pDevice->surfaceFormatCount) {
710 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600711 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600712 "%s() called before calling "
713 "vkGetSurfaceFormatsKHR().",
714 fn);
715 } else {
716 // Validate pCreateInfo->imageFormat against
717 // VkSurfaceFormatKHR::format:
718 bool foundFormat = false;
719 bool foundColorSpace = false;
720 bool foundMatch = false;
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600721 for (uint32_t i = 0 ; i < pDevice->surfaceFormatCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600722 if (pCreateInfo->imageFormat == pDevice->pSurfaceFormats[i].format) {
723 // Validate pCreateInfo->imageColorSpace against
724 // VkSurfaceFormatKHR::colorSpace:
725 foundFormat = true;
726 if (pCreateInfo->imageColorSpace == pDevice->pSurfaceFormats[i].colorSpace) {
727 foundMatch = true;
728 break;
729 }
730 } else {
731 if (pCreateInfo->imageColorSpace == pDevice->pSurfaceFormats[i].colorSpace) {
732 foundColorSpace = true;
733 }
734 }
735 }
736 if (!foundMatch) {
737 if (!foundFormat) {
738 if (!foundColorSpace) {
739 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device,
740 "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600741 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600742 "%s() called with neither a "
743 "supported pCreateInfo->imageFormat "
744 "(i.e. %d) nor a supported "
745 "pCreateInfo->imageColorSpace "
746 "(i.e. %d).",
747 fn,
748 pCreateInfo->imageFormat,
749 pCreateInfo->imageColorSpace);
750 } else {
751 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device,
Ian Elliottb0f474c2015-09-25 15:50:55 -0600752 "VkDevice",
753 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600754 "%s() called with a non-supported "
755 "pCreateInfo->imageFormat (i.e. %d).",
756 fn, pCreateInfo->imageFormat);
757 }
758 } else if (!foundColorSpace) {
759 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600760 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600761 "%s() called with a non-supported "
762 "pCreateInfo->imageColorSpace (i.e. %d).",
763 fn, pCreateInfo->imageColorSpace);
764 }
765 }
766 }
767 if (!pDevice->presentModeCount) {
768 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600769 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600770 "%s() called before calling "
771 "vkGetSurfacePresentModesKHR().",
772 fn);
773 } else {
774 // Validate pCreateInfo->presentMode against
775 // vkGetSurfacePresentModesKHR():
776 bool foundMatch = false;
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600777 for (uint32_t i = 0 ; i < pDevice->presentModeCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600778 if (pDevice->pPresentModes[i] == pCreateInfo->presentMode) {
779 foundMatch = true;
780 break;
781 }
782 }
783 if (!foundMatch) {
784 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600785 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600786 "%s() called with a non-supported "
787 "pCreateInfo->presentMode (i.e. %s).",
788 fn,
789 presentModeStr(pCreateInfo->presentMode));
790 }
791 }
792
793 // TODO: Validate the following values:
794 // - pCreateInfo->sharingMode
Chia-I Wud50a7d72015-10-26 20:48:51 +0800795 // - pCreateInfo->queueFamilyIndexCount
Ian Elliott0b4d6242015-09-22 10:51:24 -0600796 // - pCreateInfo->pQueueFamilyIndices
797 // - pCreateInfo->oldSwapchain
798
799 return skipCall;
800}
801
802VK_LAYER_EXPORT VkResult VKAPI vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, VkSwapchainKHR* pSwapchain)
803{
804 VkResult result = VK_SUCCESS;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600805 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600806 VkBool32 skipCall = validateCreateSwapchainKHR(device, pCreateInfo,
807 pSwapchain);
808
809 if (VK_FALSE == skipCall) {
810 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600811 result = my_data->device_dispatch_table->CreateSwapchainKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600812 device, pCreateInfo, pSwapchain);
813
814 if (result == VK_SUCCESS) {
815 // Remember the swapchain's handle, and link it to the device:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600816 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600817
Tobin Ehlis711ff312015-10-29 12:58:13 -0600818 my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
Chia-I Wue2fc5522015-10-26 20:04:44 +0800819 pDevice->swapchains[*pSwapchain] =
Tobin Ehlis711ff312015-10-29 12:58:13 -0600820 &my_data->swapchainMap[*pSwapchain];
821 my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
822 my_data->swapchainMap[*pSwapchain].imageCount = 0;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600823 }
824
825 return result;
826 }
827 return VK_ERROR_VALIDATION_FAILED;
828}
829
830VK_LAYER_EXPORT VkResult VKAPI vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain)
831{
832 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600833 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600834
835 // Validate that a valid VkDevice was used, and that the device
836 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600837 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600838 if (!pDevice) {
839 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
840 device,
841 "VkDevice");
842 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
843 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600844 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600845 "%s() called even though the "
846 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
847 "extension was not enabled for this VkDevice.",
848 __FUNCTION__);
849 }
850
851 // Regardless of skipCall value, do some internal cleanup:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600852 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600853 if (pSwapchain) {
854 // Delete the SwpSwapchain associated with this swapchain:
855 if (pSwapchain->pDevice) {
Chia-I Wue2fc5522015-10-26 20:04:44 +0800856 pSwapchain->pDevice->swapchains.erase(swapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600857 if (device != pSwapchain->pDevice->device) {
858 LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600859 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600860 "%s() called with a different VkDevice than the "
861 "VkSwapchainKHR was created with.",
862 __FUNCTION__);
863 }
864 }
865 if (pSwapchain->imageCount) {
866 pSwapchain->images.clear();
867 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600868 my_data->swapchainMap.erase(swapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600869 } else {
870 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Chia-I Wue2fc5522015-10-26 20:04:44 +0800871 swapchain,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600872 "VkSwapchainKHR");
873 }
874
875 if (VK_FALSE == skipCall) {
876 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600877 VkResult result = my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600878 return result;
879 }
880 return VK_ERROR_VALIDATION_FAILED;
881}
882
883VK_LAYER_EXPORT VkResult VKAPI vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pCount, VkImage* pSwapchainImages)
884{
885 VkResult result = VK_SUCCESS;
886 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600887 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600888
889 // Validate that a valid VkDevice was used, and that the device
890 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600891 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600892 if (!pDevice) {
893 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
894 device,
895 "VkDevice");
896 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
897 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600898 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600899 "%s() called even though the "
900 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
901 "extension was not enabled for this VkDevice.",
902 __FUNCTION__);
903 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600904 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600905 if (!pSwapchain) {
906 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
907 swapchain.handle,
908 "VkSwapchainKHR");
909 }
910
911 if (VK_FALSE == skipCall) {
912 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600913 result = my_data->device_dispatch_table->GetSwapchainImagesKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600914 device, swapchain, pCount, pSwapchainImages);
915
Ian Elliott66463852015-09-28 11:24:53 -0600916// TBD: Should we validate that this function was called once with
917// pSwapchainImages set to NULL (and record pCount at that time), and then
918// called again with a non-NULL pSwapchainImages?
Ian Elliott0b4d6242015-09-22 10:51:24 -0600919 if ((result == VK_SUCCESS) && pSwapchain &&pSwapchainImages &&
920 pCount && (*pCount > 0)) {
921 // Record the images and their state:
922 if (pSwapchain) {
923 pSwapchain->imageCount = *pCount;
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600924 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600925 pSwapchain->images[i].image = pSwapchainImages[i];
926 pSwapchain->images[i].pSwapchain = pSwapchain;
927 pSwapchain->images[i].ownedByApp = false;
928 }
929 }
930 }
931
932 return result;
933 }
934 return VK_ERROR_VALIDATION_FAILED;
935}
936
937VK_LAYER_EXPORT VkResult VKAPI vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, uint32_t* pImageIndex)
938{
939// TODO: Record/update the state of the swapchain, in case an error occurs
940// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
941 VkResult result = VK_SUCCESS;
942 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600943 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600944
945 // Validate that a valid VkDevice was used, and that the device
946 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600947 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600948 if (!pDevice) {
949 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
950 device,
951 "VkDevice");
952 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
953 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600954 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600955 "%s() called even though the "
956 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
957 "extension was not enabled for this VkDevice.",
958 __FUNCTION__);
959 }
960 // Validate that a valid VkSwapchainKHR was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600961 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600962 if (!pSwapchain) {
963 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Chia-I Wue2fc5522015-10-26 20:04:44 +0800964 swapchain,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600965 "VkSwapchainKHR");
966 } else {
967 // Look to see if the application is trying to own too many images at
968 // the same time (i.e. not leave any to display):
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600969 uint32_t imagesOwnedByApp = 0;
970 for (uint32_t i = 0 ; i < pSwapchain->imageCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600971 if (pSwapchain->images[i].ownedByApp) {
972 imagesOwnedByApp++;
973 }
974 }
975 if (imagesOwnedByApp >= (pSwapchain->imageCount - 1)) {
Ian Elliott4a994452015-09-24 18:33:16 -0600976 skipCall |= LOG_PERF_WARNING(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
977 swapchain,
978 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600979 SWAPCHAIN_APP_OWNS_TOO_MANY_IMAGES,
Ian Elliott4a994452015-09-24 18:33:16 -0600980 "%s() called when the application "
981 "already owns all presentable images "
982 "in this swapchain except for the "
983 "image currently being displayed. "
984 "This call to %s() cannot succeed "
985 "unless another thread calls the "
986 "vkQueuePresentKHR() function in "
987 "order to release ownership of one of "
988 "the presentable images of this "
989 "swapchain.",
990 __FUNCTION__, __FUNCTION__);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600991 }
992 }
993
994 if (VK_FALSE == skipCall) {
995 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600996 result = my_data->device_dispatch_table->AcquireNextImageKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600997 device, swapchain, timeout, semaphore, pImageIndex);
998
999 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) &&
1000 pSwapchain) {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001001 // Change the state of the image (now owned by the application):
1002 pSwapchain->images[*pImageIndex].ownedByApp = true;
1003 }
1004
1005 return result;
1006 }
1007 return VK_ERROR_VALIDATION_FAILED;
1008}
1009
1010VK_LAYER_EXPORT VkResult VKAPI vkQueuePresentKHR(VkQueue queue, VkPresentInfoKHR* pPresentInfo)
1011{
1012// TODOs:
1013//
1014// - Ensure that the queue is active, and is one of the queueFamilyIndex's
1015// that was returned by a previuos query.
1016// - Record/update the state of the swapchain, in case an error occurs
1017// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
1018 VkResult result = VK_SUCCESS;
1019 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -06001020 layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001021
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -06001022 for (uint32_t i = 0; i < pPresentInfo->swapchainCount ; i++) {
1023 uint32_t index = pPresentInfo->imageIndices[i];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001024 SwpSwapchain *pSwapchain =
Tobin Ehlis711ff312015-10-29 12:58:13 -06001025 &my_data->swapchainMap[pPresentInfo->swapchains[i]];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001026 if (pSwapchain) {
1027 if (!pSwapchain->pDevice->deviceSwapchainExtensionEnabled) {
1028 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE,
1029 pSwapchain->pDevice, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001030 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001031 "%s() called even though the "
1032 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
1033 "extension was not enabled for this "
1034 "VkDevice.",
1035 __FUNCTION__);
1036 }
1037 if (index >= pSwapchain->imageCount) {
1038 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Chia-I Wue2fc5522015-10-26 20:04:44 +08001039 pPresentInfo->swapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001040 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001041 SWAPCHAIN_INDEX_TOO_LARGE,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001042 "%s() called for an index that is too "
1043 "large (i.e. %d). There are only %d "
1044 "images in this VkSwapchainKHR.\n",
1045 __FUNCTION__, index,
1046 pSwapchain->imageCount);
1047 } else {
1048 if (!pSwapchain->images[index].ownedByApp) {
1049 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Chia-I Wue2fc5522015-10-26 20:04:44 +08001050 pPresentInfo->swapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001051 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001052 SWAPCHAIN_INDEX_NOT_IN_USE,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001053 "%s() returned an index (i.e. %d) "
1054 "for an image that is not owned by "
1055 "the application.",
1056 __FUNCTION__, index);
1057 }
1058 }
1059 } else {
1060 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Chia-I Wue2fc5522015-10-26 20:04:44 +08001061 pPresentInfo->swapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001062 "VkSwapchainKHR");
1063 }
1064 }
1065
1066 if (VK_FALSE == skipCall) {
1067 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -06001068 result = my_data->device_dispatch_table->QueuePresentKHR(queue,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001069 pPresentInfo);
1070
1071 if ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -06001072 for (uint32_t i = 0; i < pPresentInfo->swapchainCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001073 int index = pPresentInfo->imageIndices[i];
1074 SwpSwapchain *pSwapchain =
Tobin Ehlis711ff312015-10-29 12:58:13 -06001075 &my_data->swapchainMap[pPresentInfo->swapchains[i]];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001076 if (pSwapchain) {
1077 // Change the state of the image (no longer owned by the
1078 // application):
1079 pSwapchain->images[index].ownedByApp = false;
1080 }
1081 }
1082 }
1083
1084 return result;
1085 }
1086 return VK_ERROR_VALIDATION_FAILED;
1087}
1088
1089static inline PFN_vkVoidFunction layer_intercept_proc(const char *name)
1090{
1091 if (!name || name[0] != 'v' || name[1] != 'k')
1092 return NULL;
1093
1094 name += 2;
1095 if (!strcmp(name, "CreateInstance"))
1096 return (PFN_vkVoidFunction) vkCreateInstance;
1097 if (!strcmp(name, "DestroyInstance"))
1098 return (PFN_vkVoidFunction) vkDestroyInstance;
1099 if (!strcmp(name, "EnumeratePhysicalDevices"))
1100 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
1101 if (!strcmp(name, "CreateDevice"))
1102 return (PFN_vkVoidFunction) vkCreateDevice;
1103 if (!strcmp(name, "DestroyDevice"))
1104 return (PFN_vkVoidFunction) vkDestroyDevice;
1105
1106 return NULL;
1107}
1108static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name)
1109{
1110 if (!name || name[0] != 'v' || name[1] != 'k')
1111 return NULL;
1112
1113 name += 2;
1114 if (!strcmp(name, "CreateInstance"))
1115 return (PFN_vkVoidFunction) vkCreateInstance;
1116 if (!strcmp(name, "DestroyInstance"))
1117 return (PFN_vkVoidFunction) vkDestroyInstance;
1118 if (!strcmp(name, "EnumeratePhysicalDevices"))
1119 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
1120
1121 return NULL;
1122}
1123
1124VK_LAYER_EXPORT VkResult VKAPI vkDbgCreateMsgCallback(VkInstance instance, VkFlags msgFlags, const PFN_vkDbgMsgCallback pfnMsgCallback, void* pUserData, VkDbgMsgCallback* pMsgCallback)
1125{
Tobin Ehlis711ff312015-10-29 12:58:13 -06001126 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1127 VkResult result = my_data->instance_dispatch_table->DbgCreateMsgCallback(instance, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
Ian Elliott68124ac2015-10-07 16:18:35 -06001128 if (VK_SUCCESS == result) {
Ian Elliott68124ac2015-10-07 16:18:35 -06001129 result = layer_create_msg_callback(my_data->report_data, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
1130 }
1131 return result;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001132}
1133
1134VK_LAYER_EXPORT VkResult VKAPI vkDbgDestroyMsgCallback(VkInstance instance, VkDbgMsgCallback msgCallback)
1135{
Ian Elliott68124ac2015-10-07 16:18:35 -06001136 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Tobin Ehlis711ff312015-10-29 12:58:13 -06001137 VkResult result = my_data->instance_dispatch_table->DbgDestroyMsgCallback(instance, msgCallback);
Ian Elliott68124ac2015-10-07 16:18:35 -06001138 layer_destroy_msg_callback(my_data->report_data, msgCallback);
1139 return result;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001140}
1141
1142VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(VkDevice device, const char* funcName)
1143{
1144 PFN_vkVoidFunction addr;
1145 if (device == VK_NULL_HANDLE) {
1146 return NULL;
1147 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001148
Tobin Ehlis711ff312015-10-29 12:58:13 -06001149 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001150 /* loader uses this to force layer initialization; device object is wrapped */
1151 if (!strcmp("vkGetDeviceProcAddr", funcName)) {
Tobin Ehlis711ff312015-10-29 12:58:13 -06001152 VkBaseLayerObject* wrapped_dev = (VkBaseLayerObject*) device;
1153 my_data = get_my_data_ptr(get_dispatch_key(wrapped_dev->baseObject), layer_data_map);
1154 my_data->device_dispatch_table = new VkLayerDispatchTable;
1155 layer_initialize_dispatch_table(my_data->device_dispatch_table, wrapped_dev);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001156 return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
1157 }
1158
1159 addr = layer_intercept_proc(funcName);
1160 if (addr)
1161 return addr;
1162
Tobin Ehlis711ff312015-10-29 12:58:13 -06001163 my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1164 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
1165 if (my_data->deviceMap.size() != 0 &&
Mark Lobodzinski6c1cb5a2015-11-05 15:27:03 -07001166 my_data->deviceMap[device].deviceSwapchainExtensionEnabled)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001167 {
1168 if (!strcmp("vkGetSurfacePropertiesKHR", funcName))
1169 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSurfacePropertiesKHR);
1170 if (!strcmp("vkGetSurfaceFormatsKHR", funcName))
1171 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSurfaceFormatsKHR);
1172 if (!strcmp("vkGetSurfacePresentModesKHR", funcName))
1173 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSurfacePresentModesKHR);
1174 if (!strcmp("vkCreateSwapchainKHR", funcName))
1175 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateSwapchainKHR);
1176 if (!strcmp("vkDestroySwapchainKHR", funcName))
1177 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySwapchainKHR);
1178 if (!strcmp("vkGetSwapchainImagesKHR", funcName))
1179 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSwapchainImagesKHR);
1180 if (!strcmp("vkAcquireNextImageKHR", funcName))
1181 return reinterpret_cast<PFN_vkVoidFunction>(vkAcquireNextImageKHR);
1182 if (!strcmp("vkQueuePresentKHR", funcName))
1183 return reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR);
1184 }
1185 {
1186 if (pDisp->GetDeviceProcAddr == NULL)
1187 return NULL;
1188 return pDisp->GetDeviceProcAddr(device, funcName);
1189 }
1190}
1191
1192VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
1193{
1194 PFN_vkVoidFunction addr;
1195 if (instance == VK_NULL_HANDLE) {
1196 return NULL;
1197 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001198
Tobin Ehlis711ff312015-10-29 12:58:13 -06001199 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001200 /* loader uses this to force layer initialization; instance object is wrapped */
1201 if (!strcmp("vkGetInstanceProcAddr", funcName)) {
Tobin Ehlis711ff312015-10-29 12:58:13 -06001202 VkBaseLayerObject* wrapped_inst = (VkBaseLayerObject*) instance;
1203 my_data = get_my_data_ptr(get_dispatch_key(wrapped_inst->baseObject), layer_data_map);
1204 my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
1205 layer_init_instance_dispatch_table(my_data->instance_dispatch_table, wrapped_inst);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001206 return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
1207 }
1208
1209 addr = layer_intercept_instance_proc(funcName);
1210 if (addr)
1211 return addr;
1212
Tobin Ehlis711ff312015-10-29 12:58:13 -06001213 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1214 VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
Ian Elliott68124ac2015-10-07 16:18:35 -06001215 addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
1216 if (addr) {
1217 return addr;
1218 }
1219
Tobin Ehlis711ff312015-10-29 12:58:13 -06001220 if (my_data->instanceMap.size() != 0 &&
1221 my_data->instanceMap[instance].swapchainExtensionEnabled)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001222 {
1223 if (!strcmp("vkGetPhysicalDeviceSurfaceSupportKHR", funcName))
1224 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceSupportKHR);
1225 }
1226
1227 if (pTable->GetInstanceProcAddr == NULL)
1228 return NULL;
1229 return pTable->GetInstanceProcAddr(instance, funcName);
1230}
1231