blob: 0075b6f8f93965a4be83a3d74079cb42692a1f10 [file] [log] [blame]
Ian Elliott0b4d6242015-09-22 10:51:24 -06001/*
2 * Vulkan
3 *
4 * Copyright (C) 2015 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Ian Elliott <ian@lunarg.com>
26 */
27
Ian Elliottd8c5db12015-10-07 11:32:31 -060028#include <stdio.h>
29#include <string.h>
Ian Elliott0b4d6242015-09-22 10:51:24 -060030#include "swapchain.h"
Tobin Ehlis711ff312015-10-29 12:58:13 -060031#include "vk_layer_extension_utils.h"
Ian Elliott68124ac2015-10-07 16:18:35 -060032
Ian Elliott0b4d6242015-09-22 10:51:24 -060033// FIXME/TODO: Make sure this layer is thread-safe!
34
Ian Elliott68124ac2015-10-07 16:18:35 -060035
Ian Elliott0b4d6242015-09-22 10:51:24 -060036// The following is for logging error messages:
Ian Elliott68124ac2015-10-07 16:18:35 -060037static std::unordered_map<void *, layer_data *> layer_data_map;
Ian Elliott0b4d6242015-09-22 10:51:24 -060038
Ian Elliott68124ac2015-10-07 16:18:35 -060039template layer_data *get_my_data_ptr<layer_data>(
40 void *data_key,
41 std::unordered_map<void *, layer_data *> &data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -060042
Ian Elliott0b4d6242015-09-22 10:51:24 -060043
Ian Elliott0b4d6242015-09-22 10:51:24 -060044static void createDeviceRegisterExtensions(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, VkDevice device)
45{
46 uint32_t i;
Tobin Ehlis711ff312015-10-29 12:58:13 -060047 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
48 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
Ian Elliott0b4d6242015-09-22 10:51:24 -060049 PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr;
50 pDisp->GetSurfacePropertiesKHR = (PFN_vkGetSurfacePropertiesKHR) gpa(device, "vkGetSurfacePropertiesKHR");
51 pDisp->GetSurfaceFormatsKHR = (PFN_vkGetSurfaceFormatsKHR) gpa(device, "vkGetSurfaceFormatsKHR");
52 pDisp->GetSurfacePresentModesKHR = (PFN_vkGetSurfacePresentModesKHR) gpa(device, "vkGetSurfacePresentModesKHR");
53 pDisp->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR) gpa(device, "vkCreateSwapchainKHR");
54 pDisp->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR) gpa(device, "vkDestroySwapchainKHR");
55 pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR) gpa(device, "vkGetSwapchainImagesKHR");
56 pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR) gpa(device, "vkAcquireNextImageKHR");
57 pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR) gpa(device, "vkQueuePresentKHR");
58
Tobin Ehlis711ff312015-10-29 12:58:13 -060059 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -060060 if (pPhysicalDevice) {
Tobin Ehlis711ff312015-10-29 12:58:13 -060061 my_data->deviceMap[device].pPhysicalDevice = pPhysicalDevice;
62 pPhysicalDevice->pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -060063 } else {
Ian Elliott68124ac2015-10-07 16:18:35 -060064 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -060065 LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_PHYSICAL_DEVICE,
66 physicalDevice,
67 "VkPhysicalDevice");
68 }
Tobin Ehlis711ff312015-10-29 12:58:13 -060069 my_data->deviceMap[device].device = device;
70 my_data->deviceMap[device].deviceSwapchainExtensionEnabled = false;
71 my_data->deviceMap[device].gotSurfaceProperties = false;
72 my_data->deviceMap[device].surfaceFormatCount = 0;
73 my_data->deviceMap[device].pSurfaceFormats = NULL;
74 my_data->deviceMap[device].presentModeCount = 0;
75 my_data->deviceMap[device].pPresentModes = NULL;
Ian Elliott0b4d6242015-09-22 10:51:24 -060076
77 // Record whether the WSI device extension was enabled for this VkDevice.
78 // No need to check if the extension was advertised by
79 // vkEnumerateDeviceExtensionProperties(), since the loader handles that.
Chia-I Wud50a7d72015-10-26 20:48:51 +080080 for (i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -060081 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME) == 0) {
82
Tobin Ehlis711ff312015-10-29 12:58:13 -060083 my_data->deviceMap[device].deviceSwapchainExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -060084 }
85 }
86}
87
88static void createInstanceRegisterExtensions(const VkInstanceCreateInfo* pCreateInfo, VkInstance instance)
89{
90 uint32_t i;
Tobin Ehlis711ff312015-10-29 12:58:13 -060091 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
92 VkLayerInstanceDispatchTable *pDisp = my_data->instance_dispatch_table;
Ian Elliott0b4d6242015-09-22 10:51:24 -060093 PFN_vkGetInstanceProcAddr gpa = pDisp->GetInstanceProcAddr;
94 pDisp->GetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceSupportKHR");
95
96 // Remember this instance, and whether the VK_EXT_KHR_swapchain extension
97 // was enabled for it:
Tobin Ehlis711ff312015-10-29 12:58:13 -060098 my_data->instanceMap[instance].instance = instance;
99 my_data->instanceMap[instance].swapchainExtensionEnabled = false;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600100
101 // Record whether the WSI instance extension was enabled for this
102 // VkInstance. No need to check if the extension was advertised by
103 // vkEnumerateInstanceExtensionProperties(), since the loader handles that.
Chia-I Wud50a7d72015-10-26 20:48:51 +0800104 for (i = 0; i < pCreateInfo->enabledExtensionNameCount; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600105 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
106
Tobin Ehlis711ff312015-10-29 12:58:13 -0600107 my_data->instanceMap[instance].swapchainExtensionEnabled = true;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600108 }
109 }
110}
111
112
113#include "vk_dispatch_table_helper.h"
Ian Elliott68124ac2015-10-07 16:18:35 -0600114static void initSwapchain(layer_data *my_data)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600115{
116 uint32_t report_flags = 0;
117 uint32_t debug_action = 0;
118 FILE *log_output = NULL;
119 const char *option_str;
Courtney Goeltzenleuchtercf60e0a2015-10-08 17:07:25 -0600120 VkDbgMsgCallback callback;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600121
122 // Initialize Swapchain options:
123 report_flags = getLayerOptionFlags("SwapchainReportFlags", 0);
124 getLayerOptionEnum("SwapchainDebugAction", (uint32_t *) &debug_action);
125
126 if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)
127 {
128 // Turn on logging, since it was requested:
129 option_str = getLayerOption("SwapchainLogFilename");
130 log_output = getLayerLogOutput(option_str, "Swapchain");
Ian Elliott68124ac2015-10-07 16:18:35 -0600131 layer_create_msg_callback(my_data->report_data, report_flags,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600132 log_callback, (void *) log_output,
Courtney Goeltzenleuchtercf60e0a2015-10-08 17:07:25 -0600133 &callback);
134 my_data->logging_callback.push_back(callback);
135 }
136 if (debug_action & VK_DBG_LAYER_ACTION_DEBUG_OUTPUT) {
137 layer_create_msg_callback(my_data->report_data, report_flags, win32_debug_output_msg, NULL, &callback);
138 my_data->logging_callback.push_back(callback);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600139 }
140}
141
142static const char *surfaceTransformStr(VkSurfaceTransformKHR value)
143{
144 static std::string surfaceTransformStrings[] = {
145 "VK_SURFACE_TRANSFORM_NONE_KHR",
146 "VK_SURFACE_TRANSFORM_ROT90_KHR",
147 "VK_SURFACE_TRANSFORM_ROT180_KHR",
148 "VK_SURFACE_TRANSFORM_ROT270_KHR",
149 "VK_SURFACE_TRANSFORM_HMIRROR_KHR",
150 "VK_SURFACE_TRANSFORM_HMIRROR_ROT90_KHR",
151 "VK_SURFACE_TRANSFORM_HMIRROR_ROT180_KHR",
152 "VK_SURFACE_TRANSFORM_HMIRROR_ROT270_KHR",
153 "Out-of-Range Value"};
154
155 // Deal with a out-of-range value:
156 switch (value) {
157 case VK_SURFACE_TRANSFORM_NONE_KHR:
158 case VK_SURFACE_TRANSFORM_ROT90_KHR:
159 case VK_SURFACE_TRANSFORM_ROT180_KHR:
160 case VK_SURFACE_TRANSFORM_ROT270_KHR:
161 case VK_SURFACE_TRANSFORM_HMIRROR_KHR:
162 case VK_SURFACE_TRANSFORM_HMIRROR_ROT90_KHR:
163 case VK_SURFACE_TRANSFORM_HMIRROR_ROT180_KHR:
164 case VK_SURFACE_TRANSFORM_HMIRROR_ROT270_KHR:
165 break;
166 default:
167 value =
168 (VkSurfaceTransformKHR) (VK_SURFACE_TRANSFORM_HMIRROR_ROT270_KHR + 1);
169 break;
170 }
171
172 // Return a string corresponding to the value:
173 return surfaceTransformStrings[value].c_str();
174}
175
176static const char *presentModeStr(VkPresentModeKHR value)
177{
178 static std::string presentModeStrings[] = {
179 "VK_PRESENT_MODE_IMMEDIATE_KHR",
180 "VK_PRESENT_MODE_MAILBOX_KHR",
181 "VK_PRESENT_MODE_FIFO_KHR",
182 "Out-of-Range Value"};
183
184 // Deal with a out-of-range value:
185 switch (value) {
186 case VK_PRESENT_MODE_IMMEDIATE_KHR:
187 case VK_PRESENT_MODE_MAILBOX_KHR:
188 case VK_PRESENT_MODE_FIFO_KHR:
189 break;
190 default:
191 value = (VkPresentModeKHR) (VK_PRESENT_MODE_FIFO_KHR + 1);
192 break;
193 }
194
195 // Return a string corresponding to the value:
196 return presentModeStrings[value].c_str();
197}
198
199
Chia-I Wuf7458c52015-10-26 21:10:41 +0800200VK_LAYER_EXPORT VkResult VKAPI vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocCallbacks* pAllocator, VkInstance* pInstance)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600201{
Tobin Ehlis711ff312015-10-29 12:58:13 -0600202 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600203 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600204 VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
Chia-I Wuf7458c52015-10-26 21:10:41 +0800205 VkResult result = pTable->CreateInstance(pCreateInfo, pAllocator, pInstance);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600206 if (result == VK_SUCCESS) {
207 // Since it succeeded, do layer-specific work:
Ian Elliott68124ac2015-10-07 16:18:35 -0600208 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
209 my_data->report_data = debug_report_create_instance(
Tobin Ehlis711ff312015-10-29 12:58:13 -0600210 pTable,
Ian Elliott68124ac2015-10-07 16:18:35 -0600211 *pInstance,
Chia-I Wud50a7d72015-10-26 20:48:51 +0800212 pCreateInfo->enabledExtensionNameCount,
Ian Elliott68124ac2015-10-07 16:18:35 -0600213 pCreateInfo->ppEnabledExtensionNames);
214 // Call the following function after my_data is initialized:
Ian Elliott0b4d6242015-09-22 10:51:24 -0600215 createInstanceRegisterExtensions(pCreateInfo, *pInstance);
Ian Elliott68124ac2015-10-07 16:18:35 -0600216 initSwapchain(my_data);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600217 }
218 return result;
219}
220
Chia-I Wuf7458c52015-10-26 21:10:41 +0800221VK_LAYER_EXPORT void VKAPI vkDestroyInstance(VkInstance instance, const VkAllocCallbacks* pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600222{
223 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600224 dispatch_key key = get_dispatch_key(instance);
225 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600226 // Validate that a valid VkInstance was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600227 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600228 if (!pInstance) {
229 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_INSTANCE,
230 instance,
231 "VkInstance");
232 }
233
234 if (VK_FALSE == skipCall) {
235 // Call down the call chain:
Chia-I Wuf7458c52015-10-26 21:10:41 +0800236 my_data->instance_dispatch_table->DestroyInstance(instance, pAllocator);
Ian Elliott68124ac2015-10-07 16:18:35 -0600237
238 // Clean up logging callback, if any
Courtney Goeltzenleuchtercf60e0a2015-10-08 17:07:25 -0600239 while (my_data->logging_callback.size() > 0) {
240 VkDbgMsgCallback callback = my_data->logging_callback.back();
241 layer_destroy_msg_callback(my_data->report_data, callback);
242 my_data->logging_callback.pop_back();
Ian Elliott68124ac2015-10-07 16:18:35 -0600243 }
244 layer_debug_report_destroy_instance(my_data->report_data);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600245 }
246
247 // Regardless of skipCall value, do some internal cleanup:
248 if (pInstance) {
249 // Delete all of the SwpPhysicalDevice's and the SwpInstance associated
250 // with this instance:
251 for (auto it = pInstance->physicalDevices.begin() ;
252 it != pInstance->physicalDevices.end() ; it++) {
Tobin Ehlis711ff312015-10-29 12:58:13 -0600253 // Erase the SwpPhysicalDevice's from the my_data->physicalDeviceMap (which
Ian Elliott0b4d6242015-09-22 10:51:24 -0600254 // are simply pointed to by the SwpInstance):
Tobin Ehlis711ff312015-10-29 12:58:13 -0600255 my_data->physicalDeviceMap.erase(it->second->physicalDevice);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600256 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600257 my_data->instanceMap.erase(instance);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600258 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600259 delete my_data->instance_dispatch_table;
260 layer_data_map.erase(key);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600261}
262
263VK_LAYER_EXPORT VkResult VKAPI vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices)
264{
265 VkResult result = VK_SUCCESS;
266 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600267 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600268
269 // Validate that a valid VkInstance was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600270 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600271 if (!pInstance) {
272 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_INSTANCE,
273 instance,
274 "VkInstance");
275 }
276
277 if (VK_FALSE == skipCall) {
278 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600279 result = my_data->instance_dispatch_table->EnumeratePhysicalDevices(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600280 instance, pPhysicalDeviceCount, pPhysicalDevices);
281
282 if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices &&
283 (*pPhysicalDeviceCount > 0)) {
284 // Record the VkPhysicalDevices returned by the ICD:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600285 SwpInstance *pInstance = &(my_data->instanceMap[instance]);
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600286 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
Tobin Ehlis711ff312015-10-29 12:58:13 -0600287 my_data->physicalDeviceMap[pPhysicalDevices[i]].physicalDevice =
Ian Elliott0b4d6242015-09-22 10:51:24 -0600288 pPhysicalDevices[i];
Tobin Ehlis711ff312015-10-29 12:58:13 -0600289 my_data->physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance;
290 my_data->physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600291 // Point to the associated SwpInstance:
292 pInstance->physicalDevices[pPhysicalDevices[i]] =
Tobin Ehlis711ff312015-10-29 12:58:13 -0600293 &my_data->physicalDeviceMap[pPhysicalDevices[i]];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600294 }
295 }
296
297 return result;
298 }
299 return VK_ERROR_VALIDATION_FAILED;
300}
301
Chia-I Wuf7458c52015-10-26 21:10:41 +0800302VK_LAYER_EXPORT VkResult VKAPI vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocCallbacks* pAllocator, VkDevice* pDevice)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600303{
304 VkResult result = VK_SUCCESS;
305 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600306 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600307
308 // Validate that a valid VkPhysicalDevice was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600309 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600310 if (!pPhysicalDevice) {
311 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_PHYSICAL_DEVICE,
312 physicalDevice,
313 "VkPhysicalDevice");
314 }
315
Tobin Ehlis711ff312015-10-29 12:58:13 -0600316 if (VK_TRUE == skipCall)
317 return VK_ERROR_VALIDATION_FAILED;
318
319 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
320 // Call down the call chain:
321 result = my_device_data->device_dispatch_table->CreateDevice(
Chia-I Wuf7458c52015-10-26 21:10:41 +0800322 physicalDevice, pCreateInfo, pAllocator, pDevice);
Tobin Ehlis711ff312015-10-29 12:58:13 -0600323 if (result == VK_SUCCESS) {
324 // Since it succeeded, do layer-specific work:
325 my_data->report_data = layer_debug_report_create_device(my_data->report_data, *pDevice);
326 createDeviceRegisterExtensions(physicalDevice, pCreateInfo,
327 *pDevice);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600328 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600329 return result;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600330}
331
Chia-I Wuf7458c52015-10-26 21:10:41 +0800332VK_LAYER_EXPORT void VKAPI vkDestroyDevice(VkDevice device, const VkAllocCallbacks* pAllocator)
Ian Elliott0b4d6242015-09-22 10:51:24 -0600333{
334 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600335 dispatch_key key = get_dispatch_key(device);
336 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600337 // Validate that a valid VkDevice was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600338 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600339 if (!pDevice) {
340 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
341 device,
342 "VkDevice");
343 }
344
345 if (VK_FALSE == skipCall) {
346 // Call down the call chain:
Chia-I Wuf7458c52015-10-26 21:10:41 +0800347 my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600348 }
349
350 // Regardless of skipCall value, do some internal cleanup:
351 if (pDevice) {
352 // Delete the SwpDevice associated with this device:
353 if (pDevice->pPhysicalDevice) {
354 pDevice->pPhysicalDevice->pDevice = NULL;
355 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600356 if (my_data->deviceMap[device].pSurfaceFormats) {
357 free(my_data->deviceMap[device].pSurfaceFormats);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600358 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600359 if (my_data->deviceMap[device].pPresentModes) {
360 free(my_data->deviceMap[device].pPresentModes);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600361 }
Ian Elliott0b4d6242015-09-22 10:51:24 -0600362 if (!pDevice->swapchains.empty()) {
363 LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600364 SWAPCHAIN_DEL_DEVICE_BEFORE_SWAPCHAINS,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600365 "%s() called before all of its associated "
366 "VkSwapchainKHRs were destroyed.",
367 __FUNCTION__);
368 // Empty and then delete all SwpSwapchain's
369 for (auto it = pDevice->swapchains.begin() ;
370 it != pDevice->swapchains.end() ; it++) {
371 // Delete all SwpImage's
372 it->second->images.clear();
373 }
374 pDevice->swapchains.clear();
375 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600376 my_data->deviceMap.erase(device);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600377 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600378 delete my_data->device_dispatch_table;
379 layer_data_map.erase(key);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600380}
381
382VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, const VkSurfaceDescriptionKHR* pSurfaceDescription, VkBool32* pSupported)
383{
384 VkResult result = VK_SUCCESS;
385 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600386 layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600387
388 // Validate that a valid VkPhysicalDevice was used, and that the instance
389 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600390 SwpPhysicalDevice *pPhysicalDevice = &my_data->physicalDeviceMap[physicalDevice];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600391 if (!pPhysicalDevice || !pPhysicalDevice->pInstance) {
392 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_PHYSICAL_DEVICE,
393 physicalDevice,
394 "VkPhysicalDevice");
395 } else if (!pPhysicalDevice->pInstance->swapchainExtensionEnabled) {
396 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_INSTANCE,
397 pPhysicalDevice->pInstance,
398 "VkInstance",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600399 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600400 "%s() called even though the "
401 VK_EXT_KHR_SWAPCHAIN_EXTENSION_NAME,
402 "extension was not enabled for this VkInstance.",
403 __FUNCTION__);
404 }
405
406 if (VK_FALSE == skipCall) {
407 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600408 result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600409 physicalDevice, queueFamilyIndex, pSurfaceDescription,
410 pSupported);
411
412 if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
413 // Record the result of this query:
414 pPhysicalDevice->queueFamilyIndexSupport[queueFamilyIndex] =
415 *pSupported;
416 // TODO: We need to compare this with the actual queue used for
417 // presentation, to ensure it was advertised to the application as
418 // supported for presentation.
419 }
420
421 return result;
422 }
423 return VK_ERROR_VALIDATION_FAILED;
424}
425
426VK_LAYER_EXPORT VkResult VKAPI vkGetSurfacePropertiesKHR(VkDevice device, const VkSurfaceDescriptionKHR* pSurfaceDescription, VkSurfacePropertiesKHR* pSurfaceProperties)
427{
428 VkResult result = VK_SUCCESS;
429 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600430 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600431
432 // Validate that a valid VkDevice was used, and that the device
433 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600434 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600435 if (!pDevice) {
436 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
437 device,
438 "VkDevice");
439 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
440 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600441 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600442 "%s() called even though the "
443 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
444 "extension was not enabled for this VkDevice.",
445 __FUNCTION__);
446 }
447
448 if (VK_FALSE == skipCall) {
449 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600450 result = my_data->device_dispatch_table->GetSurfacePropertiesKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600451 device, pSurfaceDescription, pSurfaceProperties);
452
453 if ((result == VK_SUCCESS) && pDevice) {
454 pDevice->gotSurfaceProperties = true;
455 pDevice->surfaceProperties = *pSurfaceProperties;
456 }
457
458 return result;
459 }
460 return VK_ERROR_VALIDATION_FAILED;
461}
462
463VK_LAYER_EXPORT VkResult VKAPI vkGetSurfaceFormatsKHR(VkDevice device, const VkSurfaceDescriptionKHR* pSurfaceDescription, uint32_t* pCount, VkSurfaceFormatKHR* pSurfaceFormats)
464{
465 VkResult result = VK_SUCCESS;
466 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600467 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600468
469 // Validate that a valid VkDevice was used, and that the device
470 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600471 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600472 if (!pDevice) {
473 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
474 device,
475 "VkDevice");
476 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
477 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600478 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600479 "%s() called even though the "
480 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
481 "extension was not enabled for this VkDevice.",
482 __FUNCTION__);
483 }
484
485 if (VK_FALSE == skipCall) {
486 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600487 result = my_data->device_dispatch_table->GetSurfaceFormatsKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600488 device, pSurfaceDescription, pCount, pSurfaceFormats);
489
490 if ((result == VK_SUCCESS) && pDevice && pSurfaceFormats && pCount &&
491 (*pCount > 0)) {
492 pDevice->surfaceFormatCount = *pCount;
493 pDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)
494 malloc(*pCount * sizeof(VkSurfaceFormatKHR));
495 if (pDevice->pSurfaceFormats) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600496 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600497 pDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
498 }
499 } else {
500 pDevice->surfaceFormatCount = 0;
501 }
502 }
503
504 return result;
505 }
506 return VK_ERROR_VALIDATION_FAILED;
507}
508
509VK_LAYER_EXPORT VkResult VKAPI vkGetSurfacePresentModesKHR(VkDevice device, const VkSurfaceDescriptionKHR* pSurfaceDescription, uint32_t* pCount, VkPresentModeKHR* pPresentModes)
510{
511 VkResult result = VK_SUCCESS;
512 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600513 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600514
515 // Validate that a valid VkDevice was used, and that the device
516 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600517 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600518 if (!pDevice) {
519 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
520 device,
521 "VkDevice");
522 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
523 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600524 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600525 "%s() called even though the "
526 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
527 "extension was not enabled for this VkDevice.",
528 __FUNCTION__);
529 }
530
531 if (VK_FALSE == skipCall) {
532 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600533 result = my_data->device_dispatch_table->GetSurfacePresentModesKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600534 device, pSurfaceDescription, pCount, pPresentModes);
535
536 if ((result == VK_SUCCESS) && pDevice && pPresentModes && pCount &&
537 (*pCount > 0)) {
538 pDevice->presentModeCount = *pCount;
539 pDevice->pPresentModes = (VkPresentModeKHR *)
540 malloc(*pCount * sizeof(VkPresentModeKHR));
541 if (pDevice->pSurfaceFormats) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600542 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600543 pDevice->pPresentModes[i] = pPresentModes[i];
544 }
545 } else {
546 pDevice->presentModeCount = 0;
547 }
548 }
549
550 return result;
551 }
552 return VK_ERROR_VALIDATION_FAILED;
553}
554
555// This function does the up-front validation work for vkCreateSwapchainKHR(),
556// and returns VK_TRUE if a logging callback indicates that the call down the
557// chain should be skipped:
558static VkBool32 validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, VkSwapchainKHR* pSwapchain)
559{
560// TODO: Validate cases of re-creating a swapchain (the current code
561// assumes a new swapchain is being created).
562 VkResult result = VK_SUCCESS;
563 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600564 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600565 char fn[] = "vkCreateSwapchainKHR";
566
567 // Validate that a valid VkDevice was used, and that the device
568 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600569 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600570 if (!pDevice) {
571 return LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600572 SWAPCHAIN_INVALID_HANDLE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600573 "%s() called with a non-valid %s.",
574 fn, "VkDevice");
575
576 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
577 return LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600578 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600579 "%s() called even though the "
580 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
581 "extension was not enabled for this VkDevice.",
582 fn);
583 }
584
585 // Validate pCreateInfo with the results for previous queries:
586 if (!pDevice->gotSurfaceProperties) {
587 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600588 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600589 "%s() called before calling "
590 "vkGetSurfacePropertiesKHR().",
591 fn);
592 } else {
593 // Validate pCreateInfo->minImageCount against
594 // VkSurfacePropertiesKHR::{min|max}ImageCount:
595 VkSurfacePropertiesKHR *pProps = &pDevice->surfaceProperties;
596 if ((pCreateInfo->minImageCount < pProps->minImageCount) ||
597 ((pProps->maxImageCount > 0) &&
598 (pCreateInfo->minImageCount > pProps->maxImageCount))) {
599 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600600 SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600601 "%s() called with pCreateInfo->minImageCount "
602 "= %d, which is outside the bounds returned "
603 "by vkGetSurfacePropertiesKHR() (i.e. "
604 "minImageCount = %d, maxImageCount = %d).",
605 fn,
606 pCreateInfo->minImageCount,
607 pProps->minImageCount,
608 pProps->maxImageCount);
609 }
610 // Validate pCreateInfo->imageExtent against
611 // VkSurfacePropertiesKHR::{current|min|max}ImageExtent:
612 if ((pProps->currentExtent.width == -1) &&
613 ((pCreateInfo->imageExtent.width < pProps->minImageExtent.width) ||
614 (pCreateInfo->imageExtent.width > pProps->maxImageExtent.width) ||
615 (pCreateInfo->imageExtent.height < pProps->minImageExtent.height) ||
616 (pCreateInfo->imageExtent.height > pProps->maxImageExtent.height))) {
617 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600618 SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600619 "%s() called with pCreateInfo->imageExtent = "
620 "(%d,%d), which is outside the bounds "
621 "returned by vkGetSurfacePropertiesKHR(): "
622 "currentExtent = (%d,%d), minImageExtent = "
623 "(%d,%d), maxImageExtent = (%d,%d).",
624 fn,
625 pCreateInfo->imageExtent.width,
626 pCreateInfo->imageExtent.height,
627 pProps->currentExtent.width,
628 pProps->currentExtent.height,
629 pProps->minImageExtent.width,
630 pProps->minImageExtent.height,
631 pProps->maxImageExtent.width,
632 pProps->maxImageExtent.height);
633 }
634 if ((pProps->currentExtent.width != -1) &&
635 ((pCreateInfo->imageExtent.width != pProps->currentExtent.width) ||
636 (pCreateInfo->imageExtent.height != pProps->currentExtent.height))) {
637 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600638 SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600639 "%s() called with pCreateInfo->imageExtent = "
640 "(%d,%d), which is not equal to the "
641 "currentExtent = (%d,%d) returned by "
642 "vkGetSurfacePropertiesKHR().",
643 fn,
644 pCreateInfo->imageExtent.width,
645 pCreateInfo->imageExtent.height,
646 pProps->currentExtent.width,
647 pProps->currentExtent.height);
648 }
649 // Validate pCreateInfo->preTransform against
650 // VkSurfacePropertiesKHR::supportedTransforms:
651 if (!((1 << pCreateInfo->preTransform) & pProps->supportedTransforms)) {
652 // This is an error situation; one for which we'd like to give
653 // the developer a helpful, multi-line error message. Build it
654 // up a little at a time, and then log it:
655 std::string errorString = "";
656 char str[1024];
657 // Here's the first part of the message:
658 sprintf(str, "%s() called with a non-supported "
659 "pCreateInfo->preTransform (i.e. %s). "
660 "Supported values are:\n",
661 fn,
662 surfaceTransformStr(pCreateInfo->preTransform));
663 errorString += str;
664 for (int i = VK_SURFACE_TRANSFORM_NONE_KHR ;
665 i < VK_SURFACE_TRANSFORM_INHERIT_KHR ; i++) {
666 // Build up the rest of the message:
667 if ((1 << i) & pProps->supportedTransforms) {
668 const char *newStr =
669 surfaceTransformStr((VkSurfaceTransformKHR) (1 << i));
670 sprintf(str, " %s\n", newStr);
671 errorString += str;
672 }
673 }
674 // Log the message that we've built up:
Ian Elliott68124ac2015-10-07 16:18:35 -0600675 skipCall |= debug_report_log_msg(my_data->report_data,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600676 VK_DBG_REPORT_ERROR_BIT,
677 VK_OBJECT_TYPE_DEVICE,
Ian Elliottb0f474c2015-09-25 15:50:55 -0600678 (uint64_t) device, 0,
679 SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM,
680 LAYER_NAME,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600681 errorString.c_str());
682 }
683 // Validate pCreateInfo->imageArraySize against
684 // VkSurfacePropertiesKHR::maxImageArraySize:
685 if (pCreateInfo->imageArraySize <= pProps->maxImageArraySize) {
686 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600687 SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_SIZE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600688 "%s() called with a non-supported "
689 "pCreateInfo->imageArraySize (i.e. %d). "
690 "Maximum value is %d.",
691 fn,
692 pCreateInfo->imageArraySize,
693 pProps->maxImageArraySize);
694 }
695 // Validate pCreateInfo->imageUsageFlags against
696 // VkSurfacePropertiesKHR::supportedUsageFlags:
697 if (pCreateInfo->imageUsageFlags &&
698 (pCreateInfo->imageUsageFlags !=
699 (pCreateInfo->imageUsageFlags & pProps->supportedUsageFlags))) {
700 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600701 SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600702 "%s() called with a non-supported "
703 "pCreateInfo->imageUsageFlags (i.e. 0x%08x)."
704 " Supported flag bits are 0x%08x.",
705 fn,
706 pCreateInfo->imageUsageFlags,
707 pProps->supportedUsageFlags);
708 }
709 }
710 if (!pDevice->surfaceFormatCount) {
711 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600712 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600713 "%s() called before calling "
714 "vkGetSurfaceFormatsKHR().",
715 fn);
716 } else {
717 // Validate pCreateInfo->imageFormat against
718 // VkSurfaceFormatKHR::format:
719 bool foundFormat = false;
720 bool foundColorSpace = false;
721 bool foundMatch = false;
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600722 for (uint32_t i = 0 ; i < pDevice->surfaceFormatCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600723 if (pCreateInfo->imageFormat == pDevice->pSurfaceFormats[i].format) {
724 // Validate pCreateInfo->imageColorSpace against
725 // VkSurfaceFormatKHR::colorSpace:
726 foundFormat = true;
727 if (pCreateInfo->imageColorSpace == pDevice->pSurfaceFormats[i].colorSpace) {
728 foundMatch = true;
729 break;
730 }
731 } else {
732 if (pCreateInfo->imageColorSpace == pDevice->pSurfaceFormats[i].colorSpace) {
733 foundColorSpace = true;
734 }
735 }
736 }
737 if (!foundMatch) {
738 if (!foundFormat) {
739 if (!foundColorSpace) {
740 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device,
741 "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600742 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600743 "%s() called with neither a "
744 "supported pCreateInfo->imageFormat "
745 "(i.e. %d) nor a supported "
746 "pCreateInfo->imageColorSpace "
747 "(i.e. %d).",
748 fn,
749 pCreateInfo->imageFormat,
750 pCreateInfo->imageColorSpace);
751 } else {
752 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device,
Ian Elliottb0f474c2015-09-25 15:50:55 -0600753 "VkDevice",
754 SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600755 "%s() called with a non-supported "
756 "pCreateInfo->imageFormat (i.e. %d).",
757 fn, pCreateInfo->imageFormat);
758 }
759 } else if (!foundColorSpace) {
760 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600761 SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600762 "%s() called with a non-supported "
763 "pCreateInfo->imageColorSpace (i.e. %d).",
764 fn, pCreateInfo->imageColorSpace);
765 }
766 }
767 }
768 if (!pDevice->presentModeCount) {
769 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600770 SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600771 "%s() called before calling "
772 "vkGetSurfacePresentModesKHR().",
773 fn);
774 } else {
775 // Validate pCreateInfo->presentMode against
776 // vkGetSurfacePresentModesKHR():
777 bool foundMatch = false;
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600778 for (uint32_t i = 0 ; i < pDevice->presentModeCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600779 if (pDevice->pPresentModes[i] == pCreateInfo->presentMode) {
780 foundMatch = true;
781 break;
782 }
783 }
784 if (!foundMatch) {
785 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600786 SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600787 "%s() called with a non-supported "
788 "pCreateInfo->presentMode (i.e. %s).",
789 fn,
790 presentModeStr(pCreateInfo->presentMode));
791 }
792 }
793
794 // TODO: Validate the following values:
795 // - pCreateInfo->sharingMode
Chia-I Wud50a7d72015-10-26 20:48:51 +0800796 // - pCreateInfo->queueFamilyIndexCount
Ian Elliott0b4d6242015-09-22 10:51:24 -0600797 // - pCreateInfo->pQueueFamilyIndices
798 // - pCreateInfo->oldSwapchain
799
800 return skipCall;
801}
802
803VK_LAYER_EXPORT VkResult VKAPI vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, VkSwapchainKHR* pSwapchain)
804{
805 VkResult result = VK_SUCCESS;
Tobin Ehlis711ff312015-10-29 12:58:13 -0600806 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600807 VkBool32 skipCall = validateCreateSwapchainKHR(device, pCreateInfo,
808 pSwapchain);
809
810 if (VK_FALSE == skipCall) {
811 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600812 result = my_data->device_dispatch_table->CreateSwapchainKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600813 device, pCreateInfo, pSwapchain);
814
815 if (result == VK_SUCCESS) {
816 // Remember the swapchain's handle, and link it to the device:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600817 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600818
Tobin Ehlis711ff312015-10-29 12:58:13 -0600819 my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
Chia-I Wue2fc5522015-10-26 20:04:44 +0800820 pDevice->swapchains[*pSwapchain] =
Tobin Ehlis711ff312015-10-29 12:58:13 -0600821 &my_data->swapchainMap[*pSwapchain];
822 my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
823 my_data->swapchainMap[*pSwapchain].imageCount = 0;
Ian Elliott0b4d6242015-09-22 10:51:24 -0600824 }
825
826 return result;
827 }
828 return VK_ERROR_VALIDATION_FAILED;
829}
830
831VK_LAYER_EXPORT VkResult VKAPI vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain)
832{
833 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600834 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600835
836 // Validate that a valid VkDevice was used, and that the device
837 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600838 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600839 if (!pDevice) {
840 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
841 device,
842 "VkDevice");
843 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
844 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600845 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600846 "%s() called even though the "
847 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
848 "extension was not enabled for this VkDevice.",
849 __FUNCTION__);
850 }
851
852 // Regardless of skipCall value, do some internal cleanup:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600853 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600854 if (pSwapchain) {
855 // Delete the SwpSwapchain associated with this swapchain:
856 if (pSwapchain->pDevice) {
Chia-I Wue2fc5522015-10-26 20:04:44 +0800857 pSwapchain->pDevice->swapchains.erase(swapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600858 if (device != pSwapchain->pDevice->device) {
859 LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600860 SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600861 "%s() called with a different VkDevice than the "
862 "VkSwapchainKHR was created with.",
863 __FUNCTION__);
864 }
865 }
866 if (pSwapchain->imageCount) {
867 pSwapchain->images.clear();
868 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600869 my_data->swapchainMap.erase(swapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600870 } else {
871 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Chia-I Wue2fc5522015-10-26 20:04:44 +0800872 swapchain,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600873 "VkSwapchainKHR");
874 }
875
876 if (VK_FALSE == skipCall) {
877 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600878 VkResult result = my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600879 return result;
880 }
881 return VK_ERROR_VALIDATION_FAILED;
882}
883
884VK_LAYER_EXPORT VkResult VKAPI vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pCount, VkImage* pSwapchainImages)
885{
886 VkResult result = VK_SUCCESS;
887 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600888 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600889
890 // Validate that a valid VkDevice was used, and that the device
891 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600892 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600893 if (!pDevice) {
894 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
895 device,
896 "VkDevice");
897 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
898 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600899 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600900 "%s() called even though the "
901 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
902 "extension was not enabled for this VkDevice.",
903 __FUNCTION__);
904 }
Tobin Ehlis711ff312015-10-29 12:58:13 -0600905 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600906 if (!pSwapchain) {
907 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
908 swapchain.handle,
909 "VkSwapchainKHR");
910 }
911
912 if (VK_FALSE == skipCall) {
913 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600914 result = my_data->device_dispatch_table->GetSwapchainImagesKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600915 device, swapchain, pCount, pSwapchainImages);
916
Ian Elliott66463852015-09-28 11:24:53 -0600917// TBD: Should we validate that this function was called once with
918// pSwapchainImages set to NULL (and record pCount at that time), and then
919// called again with a non-NULL pSwapchainImages?
Ian Elliott0b4d6242015-09-22 10:51:24 -0600920 if ((result == VK_SUCCESS) && pSwapchain &&pSwapchainImages &&
921 pCount && (*pCount > 0)) {
922 // Record the images and their state:
923 if (pSwapchain) {
924 pSwapchain->imageCount = *pCount;
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600925 for (uint32_t i = 0 ; i < *pCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600926 pSwapchain->images[i].image = pSwapchainImages[i];
927 pSwapchain->images[i].pSwapchain = pSwapchain;
928 pSwapchain->images[i].ownedByApp = false;
929 }
930 }
931 }
932
933 return result;
934 }
935 return VK_ERROR_VALIDATION_FAILED;
936}
937
938VK_LAYER_EXPORT VkResult VKAPI vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, uint32_t* pImageIndex)
939{
940// TODO: Record/update the state of the swapchain, in case an error occurs
941// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
942 VkResult result = VK_SUCCESS;
943 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -0600944 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600945
946 // Validate that a valid VkDevice was used, and that the device
947 // extension was enabled:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600948 SwpDevice *pDevice = &my_data->deviceMap[device];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600949 if (!pDevice) {
950 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
951 device,
952 "VkDevice");
953 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
954 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600955 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600956 "%s() called even though the "
957 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
958 "extension was not enabled for this VkDevice.",
959 __FUNCTION__);
960 }
961 // Validate that a valid VkSwapchainKHR was used:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600962 SwpSwapchain *pSwapchain = &my_data->swapchainMap[swapchain];
Ian Elliott0b4d6242015-09-22 10:51:24 -0600963 if (!pSwapchain) {
964 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Chia-I Wue2fc5522015-10-26 20:04:44 +0800965 swapchain,
Ian Elliott0b4d6242015-09-22 10:51:24 -0600966 "VkSwapchainKHR");
967 } else {
968 // Look to see if the application is trying to own too many images at
969 // the same time (i.e. not leave any to display):
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -0600970 uint32_t imagesOwnedByApp = 0;
971 for (uint32_t i = 0 ; i < pSwapchain->imageCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -0600972 if (pSwapchain->images[i].ownedByApp) {
973 imagesOwnedByApp++;
974 }
975 }
976 if (imagesOwnedByApp >= (pSwapchain->imageCount - 1)) {
Ian Elliott4a994452015-09-24 18:33:16 -0600977 skipCall |= LOG_PERF_WARNING(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
978 swapchain,
979 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -0600980 SWAPCHAIN_APP_OWNS_TOO_MANY_IMAGES,
Ian Elliott4a994452015-09-24 18:33:16 -0600981 "%s() called when the application "
982 "already owns all presentable images "
983 "in this swapchain except for the "
984 "image currently being displayed. "
985 "This call to %s() cannot succeed "
986 "unless another thread calls the "
987 "vkQueuePresentKHR() function in "
988 "order to release ownership of one of "
989 "the presentable images of this "
990 "swapchain.",
991 __FUNCTION__, __FUNCTION__);
Ian Elliott0b4d6242015-09-22 10:51:24 -0600992 }
993 }
994
995 if (VK_FALSE == skipCall) {
996 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -0600997 result = my_data->device_dispatch_table->AcquireNextImageKHR(
Ian Elliott0b4d6242015-09-22 10:51:24 -0600998 device, swapchain, timeout, semaphore, pImageIndex);
999
1000 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) &&
1001 pSwapchain) {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001002 // Change the state of the image (now owned by the application):
1003 pSwapchain->images[*pImageIndex].ownedByApp = true;
1004 }
1005
1006 return result;
1007 }
1008 return VK_ERROR_VALIDATION_FAILED;
1009}
1010
1011VK_LAYER_EXPORT VkResult VKAPI vkQueuePresentKHR(VkQueue queue, VkPresentInfoKHR* pPresentInfo)
1012{
1013// TODOs:
1014//
1015// - Ensure that the queue is active, and is one of the queueFamilyIndex's
1016// that was returned by a previuos query.
1017// - Record/update the state of the swapchain, in case an error occurs
1018// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
1019 VkResult result = VK_SUCCESS;
1020 VkBool32 skipCall = VK_FALSE;
Ian Elliott68124ac2015-10-07 16:18:35 -06001021 layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001022
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -06001023 for (uint32_t i = 0; i < pPresentInfo->swapchainCount ; i++) {
1024 uint32_t index = pPresentInfo->imageIndices[i];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001025 SwpSwapchain *pSwapchain =
Tobin Ehlis711ff312015-10-29 12:58:13 -06001026 &my_data->swapchainMap[pPresentInfo->swapchains[i]];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001027 if (pSwapchain) {
1028 if (!pSwapchain->pDevice->deviceSwapchainExtensionEnabled) {
1029 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE,
1030 pSwapchain->pDevice, "VkDevice",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001031 SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001032 "%s() called even though the "
1033 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
1034 "extension was not enabled for this "
1035 "VkDevice.",
1036 __FUNCTION__);
1037 }
1038 if (index >= pSwapchain->imageCount) {
1039 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Chia-I Wue2fc5522015-10-26 20:04:44 +08001040 pPresentInfo->swapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001041 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001042 SWAPCHAIN_INDEX_TOO_LARGE,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001043 "%s() called for an index that is too "
1044 "large (i.e. %d). There are only %d "
1045 "images in this VkSwapchainKHR.\n",
1046 __FUNCTION__, index,
1047 pSwapchain->imageCount);
1048 } else {
1049 if (!pSwapchain->images[index].ownedByApp) {
1050 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Chia-I Wue2fc5522015-10-26 20:04:44 +08001051 pPresentInfo->swapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001052 "VkSwapchainKHR",
Ian Elliottb0f474c2015-09-25 15:50:55 -06001053 SWAPCHAIN_INDEX_NOT_IN_USE,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001054 "%s() returned an index (i.e. %d) "
1055 "for an image that is not owned by "
1056 "the application.",
1057 __FUNCTION__, index);
1058 }
1059 }
1060 } else {
1061 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
Chia-I Wue2fc5522015-10-26 20:04:44 +08001062 pPresentInfo->swapchains[i],
Ian Elliott0b4d6242015-09-22 10:51:24 -06001063 "VkSwapchainKHR");
1064 }
1065 }
1066
1067 if (VK_FALSE == skipCall) {
1068 // Call down the call chain:
Tobin Ehlis711ff312015-10-29 12:58:13 -06001069 result = my_data->device_dispatch_table->QueuePresentKHR(queue,
Ian Elliott0b4d6242015-09-22 10:51:24 -06001070 pPresentInfo);
1071
1072 if ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) {
Courtney Goeltzenleuchterdad30df2015-10-07 09:00:34 -06001073 for (uint32_t i = 0; i < pPresentInfo->swapchainCount ; i++) {
Ian Elliott0b4d6242015-09-22 10:51:24 -06001074 int index = pPresentInfo->imageIndices[i];
1075 SwpSwapchain *pSwapchain =
Tobin Ehlis711ff312015-10-29 12:58:13 -06001076 &my_data->swapchainMap[pPresentInfo->swapchains[i]];
Ian Elliott0b4d6242015-09-22 10:51:24 -06001077 if (pSwapchain) {
1078 // Change the state of the image (no longer owned by the
1079 // application):
1080 pSwapchain->images[index].ownedByApp = false;
1081 }
1082 }
1083 }
1084
1085 return result;
1086 }
1087 return VK_ERROR_VALIDATION_FAILED;
1088}
1089
1090static inline PFN_vkVoidFunction layer_intercept_proc(const char *name)
1091{
1092 if (!name || name[0] != 'v' || name[1] != 'k')
1093 return NULL;
1094
1095 name += 2;
1096 if (!strcmp(name, "CreateInstance"))
1097 return (PFN_vkVoidFunction) vkCreateInstance;
1098 if (!strcmp(name, "DestroyInstance"))
1099 return (PFN_vkVoidFunction) vkDestroyInstance;
1100 if (!strcmp(name, "EnumeratePhysicalDevices"))
1101 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
1102 if (!strcmp(name, "CreateDevice"))
1103 return (PFN_vkVoidFunction) vkCreateDevice;
1104 if (!strcmp(name, "DestroyDevice"))
1105 return (PFN_vkVoidFunction) vkDestroyDevice;
1106
1107 return NULL;
1108}
1109static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name)
1110{
1111 if (!name || name[0] != 'v' || name[1] != 'k')
1112 return NULL;
1113
1114 name += 2;
1115 if (!strcmp(name, "CreateInstance"))
1116 return (PFN_vkVoidFunction) vkCreateInstance;
1117 if (!strcmp(name, "DestroyInstance"))
1118 return (PFN_vkVoidFunction) vkDestroyInstance;
1119 if (!strcmp(name, "EnumeratePhysicalDevices"))
1120 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
1121
1122 return NULL;
1123}
1124
1125VK_LAYER_EXPORT VkResult VKAPI vkDbgCreateMsgCallback(VkInstance instance, VkFlags msgFlags, const PFN_vkDbgMsgCallback pfnMsgCallback, void* pUserData, VkDbgMsgCallback* pMsgCallback)
1126{
Tobin Ehlis711ff312015-10-29 12:58:13 -06001127 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1128 VkResult result = my_data->instance_dispatch_table->DbgCreateMsgCallback(instance, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
Ian Elliott68124ac2015-10-07 16:18:35 -06001129 if (VK_SUCCESS == result) {
Ian Elliott68124ac2015-10-07 16:18:35 -06001130 result = layer_create_msg_callback(my_data->report_data, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
1131 }
1132 return result;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001133}
1134
1135VK_LAYER_EXPORT VkResult VKAPI vkDbgDestroyMsgCallback(VkInstance instance, VkDbgMsgCallback msgCallback)
1136{
Ian Elliott68124ac2015-10-07 16:18:35 -06001137 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Tobin Ehlis711ff312015-10-29 12:58:13 -06001138 VkResult result = my_data->instance_dispatch_table->DbgDestroyMsgCallback(instance, msgCallback);
Ian Elliott68124ac2015-10-07 16:18:35 -06001139 layer_destroy_msg_callback(my_data->report_data, msgCallback);
1140 return result;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001141}
1142
1143VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(VkDevice device, const char* funcName)
1144{
1145 PFN_vkVoidFunction addr;
1146 if (device == VK_NULL_HANDLE) {
1147 return NULL;
1148 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001149
Tobin Ehlis711ff312015-10-29 12:58:13 -06001150 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001151 /* loader uses this to force layer initialization; device object is wrapped */
1152 if (!strcmp("vkGetDeviceProcAddr", funcName)) {
Tobin Ehlis711ff312015-10-29 12:58:13 -06001153 VkBaseLayerObject* wrapped_dev = (VkBaseLayerObject*) device;
1154 my_data = get_my_data_ptr(get_dispatch_key(wrapped_dev->baseObject), layer_data_map);
1155 my_data->device_dispatch_table = new VkLayerDispatchTable;
1156 layer_initialize_dispatch_table(my_data->device_dispatch_table, wrapped_dev);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001157 return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
1158 }
1159
1160 addr = layer_intercept_proc(funcName);
1161 if (addr)
1162 return addr;
1163
Tobin Ehlis711ff312015-10-29 12:58:13 -06001164 my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1165 VkLayerDispatchTable *pDisp = my_data->device_dispatch_table;
1166 if (my_data->deviceMap.size() != 0 &&
1167 my_data->deviceMap[pDisp].deviceSwapchainExtensionEnabled)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001168 {
1169 if (!strcmp("vkGetSurfacePropertiesKHR", funcName))
1170 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSurfacePropertiesKHR);
1171 if (!strcmp("vkGetSurfaceFormatsKHR", funcName))
1172 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSurfaceFormatsKHR);
1173 if (!strcmp("vkGetSurfacePresentModesKHR", funcName))
1174 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSurfacePresentModesKHR);
1175 if (!strcmp("vkCreateSwapchainKHR", funcName))
1176 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateSwapchainKHR);
1177 if (!strcmp("vkDestroySwapchainKHR", funcName))
1178 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySwapchainKHR);
1179 if (!strcmp("vkGetSwapchainImagesKHR", funcName))
1180 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSwapchainImagesKHR);
1181 if (!strcmp("vkAcquireNextImageKHR", funcName))
1182 return reinterpret_cast<PFN_vkVoidFunction>(vkAcquireNextImageKHR);
1183 if (!strcmp("vkQueuePresentKHR", funcName))
1184 return reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR);
1185 }
1186 {
1187 if (pDisp->GetDeviceProcAddr == NULL)
1188 return NULL;
1189 return pDisp->GetDeviceProcAddr(device, funcName);
1190 }
1191}
1192
1193VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
1194{
1195 PFN_vkVoidFunction addr;
1196 if (instance == VK_NULL_HANDLE) {
1197 return NULL;
1198 }
Ian Elliott0b4d6242015-09-22 10:51:24 -06001199
Tobin Ehlis711ff312015-10-29 12:58:13 -06001200 layer_data *my_data;
Ian Elliott0b4d6242015-09-22 10:51:24 -06001201 /* loader uses this to force layer initialization; instance object is wrapped */
1202 if (!strcmp("vkGetInstanceProcAddr", funcName)) {
Tobin Ehlis711ff312015-10-29 12:58:13 -06001203 VkBaseLayerObject* wrapped_inst = (VkBaseLayerObject*) instance;
1204 my_data = get_my_data_ptr(get_dispatch_key(wrapped_inst->baseObject), layer_data_map);
1205 my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
1206 layer_init_instance_dispatch_table(my_data->instance_dispatch_table, wrapped_inst);
Ian Elliott0b4d6242015-09-22 10:51:24 -06001207 return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
1208 }
1209
1210 addr = layer_intercept_instance_proc(funcName);
1211 if (addr)
1212 return addr;
1213
Tobin Ehlis711ff312015-10-29 12:58:13 -06001214 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1215 VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
Ian Elliott68124ac2015-10-07 16:18:35 -06001216 addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
1217 if (addr) {
1218 return addr;
1219 }
1220
Tobin Ehlis711ff312015-10-29 12:58:13 -06001221 if (my_data->instanceMap.size() != 0 &&
1222 my_data->instanceMap[instance].swapchainExtensionEnabled)
Ian Elliott0b4d6242015-09-22 10:51:24 -06001223 {
1224 if (!strcmp("vkGetPhysicalDeviceSurfaceSupportKHR", funcName))
1225 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceSupportKHR);
1226 }
1227
1228 if (pTable->GetInstanceProcAddr == NULL)
1229 return NULL;
1230 return pTable->GetInstanceProcAddr(instance, funcName);
1231}
1232