blob: 00286576dc1de7dd2805c6da0fea26f5dbbffdbb [file] [log] [blame]
Ian Elliott329da012015-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
28#include "swapchain.h"
29
30// FIXME/TODO: Make sure this layer is thread-safe!
31
32// The following is for logging error messages:
33static layer_data mydata;
34
35
36static const VkLayerProperties globalLayerProps[] = {
37 {
38 "Swapchain",
39 VK_API_VERSION, // specVersion
40 VK_MAKE_VERSION(0, 1, 0), // implVersion
41 "layer: Swapchain",
42 }
43};
44
45static const VkLayerProperties deviceLayerProps[] = {
46 {
47 "Swapchain",
48 VK_API_VERSION, // specVersion
49 VK_MAKE_VERSION(0, 1, 0), // implVersion
50 "layer: Swapchain",
51 }
52};
53
54
55static LOADER_PLATFORM_THREAD_ONCE_DECLARATION(initOnce);
56
57// NOTE: The following are for keeping track of info that is used for
58// validating the WSI extensions.
59static std::unordered_map<void *, SwpInstance> instanceMap;
60static std::unordered_map<void *, SwpPhysicalDevice> physicalDeviceMap;
61static std::unordered_map<void *, SwpDevice> deviceMap;
62static std::unordered_map<uint64_t, SwpSwapchain> swapchainMap;
63
64
65static void createDeviceRegisterExtensions(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, VkDevice device)
66{
67 uint32_t i;
68 VkLayerDispatchTable *pDisp = device_dispatch_table(device);
69 PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr;
70 pDisp->GetSurfacePropertiesKHR = (PFN_vkGetSurfacePropertiesKHR) gpa(device, "vkGetSurfacePropertiesKHR");
71 pDisp->GetSurfaceFormatsKHR = (PFN_vkGetSurfaceFormatsKHR) gpa(device, "vkGetSurfaceFormatsKHR");
72 pDisp->GetSurfacePresentModesKHR = (PFN_vkGetSurfacePresentModesKHR) gpa(device, "vkGetSurfacePresentModesKHR");
73 pDisp->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR) gpa(device, "vkCreateSwapchainKHR");
74 pDisp->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR) gpa(device, "vkDestroySwapchainKHR");
75 pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR) gpa(device, "vkGetSwapchainImagesKHR");
76 pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR) gpa(device, "vkAcquireNextImageKHR");
77 pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR) gpa(device, "vkQueuePresentKHR");
78
79 SwpPhysicalDevice *pPhysicalDevice = &physicalDeviceMap[physicalDevice];
80 if (pPhysicalDevice) {
81 deviceMap[device].pPhysicalDevice = pPhysicalDevice;
82 pPhysicalDevice->pDevice = &deviceMap[device];
83 } else {
84 LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_PHYSICAL_DEVICE,
85 physicalDevice,
86 "VkPhysicalDevice");
87 }
88 deviceMap[device].device = device;
89 deviceMap[device].deviceSwapchainExtensionEnabled = false;
90 deviceMap[device].gotSurfaceProperties = false;
91 deviceMap[device].surfaceFormatCount = 0;
92 deviceMap[device].pSurfaceFormats = NULL;
93 deviceMap[device].presentModeCount = 0;
94 deviceMap[device].pPresentModes = NULL;
95
96 // Record whether the WSI device extension was enabled for this VkDevice.
97 // No need to check if the extension was advertised by
98 // vkEnumerateDeviceExtensionProperties(), since the loader handles that.
99 for (i = 0; i < pCreateInfo->extensionCount; i++) {
100 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME) == 0) {
101
102 deviceMap[device].deviceSwapchainExtensionEnabled = true;
103 }
104 }
105}
106
107static void createInstanceRegisterExtensions(const VkInstanceCreateInfo* pCreateInfo, VkInstance instance)
108{
109 uint32_t i;
110 VkLayerInstanceDispatchTable *pDisp = instance_dispatch_table(instance);
111 PFN_vkGetInstanceProcAddr gpa = pDisp->GetInstanceProcAddr;
112 pDisp->GetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR) gpa(instance, "vkGetPhysicalDeviceSurfaceSupportKHR");
113
114 // Remember this instance, and whether the VK_EXT_KHR_swapchain extension
115 // was enabled for it:
116 instanceMap[instance].instance = instance;
117 instanceMap[instance].swapchainExtensionEnabled = false;
118
119 // Record whether the WSI instance extension was enabled for this
120 // VkInstance. No need to check if the extension was advertised by
121 // vkEnumerateInstanceExtensionProperties(), since the loader handles that.
122 for (i = 0; i < pCreateInfo->extensionCount; i++) {
123 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_EXT_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
124
125 instanceMap[instance].swapchainExtensionEnabled = true;
126 }
127 }
128}
129
130
131#include "vk_dispatch_table_helper.h"
132static void initSwapchain(void)
133{
134 uint32_t report_flags = 0;
135 uint32_t debug_action = 0;
136 FILE *log_output = NULL;
137 const char *option_str;
138
139 // Initialize Swapchain options:
140 report_flags = getLayerOptionFlags("SwapchainReportFlags", 0);
141 getLayerOptionEnum("SwapchainDebugAction", (uint32_t *) &debug_action);
142
143 if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)
144 {
145 // Turn on logging, since it was requested:
146 option_str = getLayerOption("SwapchainLogFilename");
147 log_output = getLayerLogOutput(option_str, "Swapchain");
148 layer_create_msg_callback(&mydata.report_data, report_flags,
149 log_callback, (void *) log_output,
150 &mydata.logging_callback);
151 }
152}
153
154static const char *surfaceTransformStr(VkSurfaceTransformKHR value)
155{
156 static std::string surfaceTransformStrings[] = {
157 "VK_SURFACE_TRANSFORM_NONE_KHR",
158 "VK_SURFACE_TRANSFORM_ROT90_KHR",
159 "VK_SURFACE_TRANSFORM_ROT180_KHR",
160 "VK_SURFACE_TRANSFORM_ROT270_KHR",
161 "VK_SURFACE_TRANSFORM_HMIRROR_KHR",
162 "VK_SURFACE_TRANSFORM_HMIRROR_ROT90_KHR",
163 "VK_SURFACE_TRANSFORM_HMIRROR_ROT180_KHR",
164 "VK_SURFACE_TRANSFORM_HMIRROR_ROT270_KHR",
165 "Out-of-Range Value"};
166
167 // Deal with a out-of-range value:
168 switch (value) {
169 case VK_SURFACE_TRANSFORM_NONE_KHR:
170 case VK_SURFACE_TRANSFORM_ROT90_KHR:
171 case VK_SURFACE_TRANSFORM_ROT180_KHR:
172 case VK_SURFACE_TRANSFORM_ROT270_KHR:
173 case VK_SURFACE_TRANSFORM_HMIRROR_KHR:
174 case VK_SURFACE_TRANSFORM_HMIRROR_ROT90_KHR:
175 case VK_SURFACE_TRANSFORM_HMIRROR_ROT180_KHR:
176 case VK_SURFACE_TRANSFORM_HMIRROR_ROT270_KHR:
177 break;
178 default:
179 value =
180 (VkSurfaceTransformKHR) (VK_SURFACE_TRANSFORM_HMIRROR_ROT270_KHR + 1);
181 break;
182 }
183
184 // Return a string corresponding to the value:
185 return surfaceTransformStrings[value].c_str();
186}
187
188static const char *presentModeStr(VkPresentModeKHR value)
189{
190 static std::string presentModeStrings[] = {
191 "VK_PRESENT_MODE_IMMEDIATE_KHR",
192 "VK_PRESENT_MODE_MAILBOX_KHR",
193 "VK_PRESENT_MODE_FIFO_KHR",
194 "Out-of-Range Value"};
195
196 // Deal with a out-of-range value:
197 switch (value) {
198 case VK_PRESENT_MODE_IMMEDIATE_KHR:
199 case VK_PRESENT_MODE_MAILBOX_KHR:
200 case VK_PRESENT_MODE_FIFO_KHR:
201 break;
202 default:
203 value = (VkPresentModeKHR) (VK_PRESENT_MODE_FIFO_KHR + 1);
204 break;
205 }
206
207 // Return a string corresponding to the value:
208 return presentModeStrings[value].c_str();
209}
210
211
212VK_LAYER_EXPORT VkResult VKAPI vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, VkInstance* pInstance)
213{
214 // Call down the call chain:
215 VkResult result = instance_dispatch_table(*pInstance)->CreateInstance(pCreateInfo, pInstance);
216 if (result == VK_SUCCESS) {
217 // Since it succeeded, do layer-specific work:
218 createInstanceRegisterExtensions(pCreateInfo, *pInstance);
219 }
220 return result;
221}
222
223VK_LAYER_EXPORT void VKAPI vkDestroyInstance(VkInstance instance)
224{
225 VkBool32 skipCall = VK_FALSE;
226
227 // Validate that a valid VkInstance was used:
228 SwpInstance *pInstance = &instanceMap[instance];
229 if (!pInstance) {
230 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_INSTANCE,
231 instance,
232 "VkInstance");
233 }
234
235 if (VK_FALSE == skipCall) {
236 // Call down the call chain:
237 dispatch_key key = get_dispatch_key(instance);
238 VkLayerInstanceDispatchTable *pDisp = instance_dispatch_table(instance);
239 pDisp->DestroyInstance(instance);
240 destroy_instance_dispatch_table(key);
241 }
242
243 // Regardless of skipCall value, do some internal cleanup:
244 if (pInstance) {
245 // Delete all of the SwpPhysicalDevice's and the SwpInstance associated
246 // with this instance:
247 for (auto it = pInstance->physicalDevices.begin() ;
248 it != pInstance->physicalDevices.end() ; it++) {
249 // Erase the SwpPhysicalDevice's from the physicalDeviceMap (which
250 // are simply pointed to by the SwpInstance):
251 physicalDeviceMap.erase(it->second->physicalDevice);
252 }
253 instanceMap.erase(instance);
254 }
255}
256
257VK_LAYER_EXPORT VkResult VKAPI vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices)
258{
259 VkResult result = VK_SUCCESS;
260 VkBool32 skipCall = VK_FALSE;
261
262 // Validate that a valid VkInstance was used:
263 SwpInstance *pInstance = &instanceMap[instance];
264 if (!pInstance) {
265 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_INSTANCE,
266 instance,
267 "VkInstance");
268 }
269
270 if (VK_FALSE == skipCall) {
271 // Call down the call chain:
272 result = instance_dispatch_table(instance)->EnumeratePhysicalDevices(
273 instance, pPhysicalDeviceCount, pPhysicalDevices);
274
275 if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices &&
276 (*pPhysicalDeviceCount > 0)) {
277 // Record the VkPhysicalDevices returned by the ICD:
278 SwpInstance *pInstance = &instanceMap[instance];
279 for (int i = 0; i < *pPhysicalDeviceCount; i++) {
280 physicalDeviceMap[pPhysicalDevices[i]].physicalDevice =
281 pPhysicalDevices[i];
282 physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance;
283 physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL;
284 // Point to the associated SwpInstance:
285 pInstance->physicalDevices[pPhysicalDevices[i]] =
286 &physicalDeviceMap[pPhysicalDevices[i]];
287 }
288 }
289
290 return result;
291 }
292 return VK_ERROR_VALIDATION_FAILED;
293}
294
295VK_LAYER_EXPORT VkResult VKAPI vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, VkDevice* pDevice)
296{
297 VkResult result = VK_SUCCESS;
298 VkBool32 skipCall = VK_FALSE;
299
300 // Validate that a valid VkPhysicalDevice was used:
301 SwpPhysicalDevice *pPhysicalDevice = &physicalDeviceMap[physicalDevice];
302 if (!pPhysicalDevice) {
303 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_PHYSICAL_DEVICE,
304 physicalDevice,
305 "VkPhysicalDevice");
306 }
307
308 if (VK_FALSE == skipCall) {
309 // Call down the call chain:
310 result = device_dispatch_table(*pDevice)->CreateDevice(
311 physicalDevice, pCreateInfo, pDevice);
312 if (result == VK_SUCCESS) {
313 // Since it succeeded, do layer-specific work:
314 createDeviceRegisterExtensions(physicalDevice, pCreateInfo,
315 *pDevice);
316 }
317 return result;
318 }
319 return VK_ERROR_VALIDATION_FAILED;
320}
321
322VK_LAYER_EXPORT void VKAPI vkDestroyDevice(VkDevice device)
323{
324 VkBool32 skipCall = VK_FALSE;
325
326 // Validate that a valid VkDevice was used:
327 SwpDevice *pDevice = &deviceMap[device];
328 if (!pDevice) {
329 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
330 device,
331 "VkDevice");
332 }
333
334 if (VK_FALSE == skipCall) {
335 // Call down the call chain:
336 dispatch_key key = get_dispatch_key(device);
337 VkLayerDispatchTable *pDisp = device_dispatch_table(device);
338 pDisp->DestroyDevice(device);
339 destroy_device_dispatch_table(key);
340 }
341
342 // Regardless of skipCall value, do some internal cleanup:
343 if (pDevice) {
344 // Delete the SwpDevice associated with this device:
345 if (pDevice->pPhysicalDevice) {
346 pDevice->pPhysicalDevice->pDevice = NULL;
347 }
348 if (deviceMap[device].pSurfaceFormats) {
349 free(deviceMap[device].pSurfaceFormats);
350 }
351 if (deviceMap[device].pPresentModes) {
352 free(deviceMap[device].pPresentModes);
353 }
354 deviceMap.erase(device);
355 if (!pDevice->swapchains.empty()) {
356 LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
357 "%s() called before all of its associated "
358 "VkSwapchainKHRs were destroyed.",
359 __FUNCTION__);
360 // Empty and then delete all SwpSwapchain's
361 for (auto it = pDevice->swapchains.begin() ;
362 it != pDevice->swapchains.end() ; it++) {
363 // Delete all SwpImage's
364 it->second->images.clear();
365 }
366 pDevice->swapchains.clear();
367 }
368 }
369}
370
371VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, const VkSurfaceDescriptionKHR* pSurfaceDescription, VkBool32* pSupported)
372{
373 VkResult result = VK_SUCCESS;
374 VkBool32 skipCall = VK_FALSE;
375
376 // Validate that a valid VkPhysicalDevice was used, and that the instance
377 // extension was enabled:
378 SwpPhysicalDevice *pPhysicalDevice = &physicalDeviceMap[physicalDevice];
379 if (!pPhysicalDevice || !pPhysicalDevice->pInstance) {
380 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_PHYSICAL_DEVICE,
381 physicalDevice,
382 "VkPhysicalDevice");
383 } else if (!pPhysicalDevice->pInstance->swapchainExtensionEnabled) {
384 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_INSTANCE,
385 pPhysicalDevice->pInstance,
386 "VkInstance",
387 "%s() called even though the "
388 VK_EXT_KHR_SWAPCHAIN_EXTENSION_NAME,
389 "extension was not enabled for this VkInstance.",
390 __FUNCTION__);
391 }
392
393 if (VK_FALSE == skipCall) {
394 // Call down the call chain:
395 result = instance_dispatch_table(physicalDevice)->GetPhysicalDeviceSurfaceSupportKHR(
396 physicalDevice, queueFamilyIndex, pSurfaceDescription,
397 pSupported);
398
399 if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
400 // Record the result of this query:
401 pPhysicalDevice->queueFamilyIndexSupport[queueFamilyIndex] =
402 *pSupported;
403 // TODO: We need to compare this with the actual queue used for
404 // presentation, to ensure it was advertised to the application as
405 // supported for presentation.
406 }
407
408 return result;
409 }
410 return VK_ERROR_VALIDATION_FAILED;
411}
412
413VK_LAYER_EXPORT VkResult VKAPI vkGetSurfacePropertiesKHR(VkDevice device, const VkSurfaceDescriptionKHR* pSurfaceDescription, VkSurfacePropertiesKHR* pSurfaceProperties)
414{
415 VkResult result = VK_SUCCESS;
416 VkBool32 skipCall = VK_FALSE;
417
418 // Validate that a valid VkDevice was used, and that the device
419 // extension was enabled:
420 SwpDevice *pDevice = &deviceMap[device];
421 if (!pDevice) {
422 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
423 device,
424 "VkDevice");
425 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
426 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
427 "%s() called even though the "
428 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
429 "extension was not enabled for this VkDevice.",
430 __FUNCTION__);
431 }
432
433 if (VK_FALSE == skipCall) {
434 // Call down the call chain:
435 result = device_dispatch_table(device)->GetSurfacePropertiesKHR(
436 device, pSurfaceDescription, pSurfaceProperties);
437
438 if ((result == VK_SUCCESS) && pDevice) {
439 pDevice->gotSurfaceProperties = true;
440 pDevice->surfaceProperties = *pSurfaceProperties;
441 }
442
443 return result;
444 }
445 return VK_ERROR_VALIDATION_FAILED;
446}
447
448VK_LAYER_EXPORT VkResult VKAPI vkGetSurfaceFormatsKHR(VkDevice device, const VkSurfaceDescriptionKHR* pSurfaceDescription, uint32_t* pCount, VkSurfaceFormatKHR* pSurfaceFormats)
449{
450 VkResult result = VK_SUCCESS;
451 VkBool32 skipCall = VK_FALSE;
452
453 // Validate that a valid VkDevice was used, and that the device
454 // extension was enabled:
455 SwpDevice *pDevice = &deviceMap[device];
456 if (!pDevice) {
457 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
458 device,
459 "VkDevice");
460 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
461 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
462 "%s() called even though the "
463 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
464 "extension was not enabled for this VkDevice.",
465 __FUNCTION__);
466 }
467
468 if (VK_FALSE == skipCall) {
469 // Call down the call chain:
470 result = device_dispatch_table(device)->GetSurfaceFormatsKHR(
471 device, pSurfaceDescription, pCount, pSurfaceFormats);
472
473 if ((result == VK_SUCCESS) && pDevice && pSurfaceFormats && pCount &&
474 (*pCount > 0)) {
475 pDevice->surfaceFormatCount = *pCount;
476 pDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)
477 malloc(*pCount * sizeof(VkSurfaceFormatKHR));
478 if (pDevice->pSurfaceFormats) {
479 for (int i = 0 ; i < *pCount ; i++) {
480 pDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
481 }
482 } else {
483 pDevice->surfaceFormatCount = 0;
484 }
485 }
486
487 return result;
488 }
489 return VK_ERROR_VALIDATION_FAILED;
490}
491
492VK_LAYER_EXPORT VkResult VKAPI vkGetSurfacePresentModesKHR(VkDevice device, const VkSurfaceDescriptionKHR* pSurfaceDescription, uint32_t* pCount, VkPresentModeKHR* pPresentModes)
493{
494 VkResult result = VK_SUCCESS;
495 VkBool32 skipCall = VK_FALSE;
496
497 // Validate that a valid VkDevice was used, and that the device
498 // extension was enabled:
499 SwpDevice *pDevice = &deviceMap[device];
500 if (!pDevice) {
501 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
502 device,
503 "VkDevice");
504 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
505 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
506 "%s() called even though the "
507 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
508 "extension was not enabled for this VkDevice.",
509 __FUNCTION__);
510 }
511
512 if (VK_FALSE == skipCall) {
513 // Call down the call chain:
514 result = device_dispatch_table(device)->GetSurfacePresentModesKHR(
515 device, pSurfaceDescription, pCount, pPresentModes);
516
517 if ((result == VK_SUCCESS) && pDevice && pPresentModes && pCount &&
518 (*pCount > 0)) {
519 pDevice->presentModeCount = *pCount;
520 pDevice->pPresentModes = (VkPresentModeKHR *)
521 malloc(*pCount * sizeof(VkPresentModeKHR));
522 if (pDevice->pSurfaceFormats) {
523 for (int i = 0 ; i < *pCount ; i++) {
524 pDevice->pPresentModes[i] = pPresentModes[i];
525 }
526 } else {
527 pDevice->presentModeCount = 0;
528 }
529 }
530
531 return result;
532 }
533 return VK_ERROR_VALIDATION_FAILED;
534}
535
536// This function does the up-front validation work for vkCreateSwapchainKHR(),
537// and returns VK_TRUE if a logging callback indicates that the call down the
538// chain should be skipped:
539static VkBool32 validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, VkSwapchainKHR* pSwapchain)
540{
541// TODO: Validate cases of re-creating a swapchain (the current code
542// assumes a new swapchain is being created).
543 VkResult result = VK_SUCCESS;
544 VkBool32 skipCall = VK_FALSE;
545 char fn[] = "vkCreateSwapchainKHR";
546
547 // Validate that a valid VkDevice was used, and that the device
548 // extension was enabled:
549 SwpDevice *pDevice = &deviceMap[device];
550 if (!pDevice) {
551 return LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
552 "%s() called with a non-valid %s.",
553 fn, "VkDevice");
554
555 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
556 return LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
557 "%s() called even though the "
558 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
559 "extension was not enabled for this VkDevice.",
560 fn);
561 }
562
563 // Validate pCreateInfo with the results for previous queries:
564 if (!pDevice->gotSurfaceProperties) {
565 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
566 "%s() called before calling "
567 "vkGetSurfacePropertiesKHR().",
568 fn);
569 } else {
570 // Validate pCreateInfo->minImageCount against
571 // VkSurfacePropertiesKHR::{min|max}ImageCount:
572 VkSurfacePropertiesKHR *pProps = &pDevice->surfaceProperties;
573 if ((pCreateInfo->minImageCount < pProps->minImageCount) ||
574 ((pProps->maxImageCount > 0) &&
575 (pCreateInfo->minImageCount > pProps->maxImageCount))) {
576 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
577 "%s() called with pCreateInfo->minImageCount "
578 "= %d, which is outside the bounds returned "
579 "by vkGetSurfacePropertiesKHR() (i.e. "
580 "minImageCount = %d, maxImageCount = %d).",
581 fn,
582 pCreateInfo->minImageCount,
583 pProps->minImageCount,
584 pProps->maxImageCount);
585 }
586 // Validate pCreateInfo->imageExtent against
587 // VkSurfacePropertiesKHR::{current|min|max}ImageExtent:
588 if ((pProps->currentExtent.width == -1) &&
589 ((pCreateInfo->imageExtent.width < pProps->minImageExtent.width) ||
590 (pCreateInfo->imageExtent.width > pProps->maxImageExtent.width) ||
591 (pCreateInfo->imageExtent.height < pProps->minImageExtent.height) ||
592 (pCreateInfo->imageExtent.height > pProps->maxImageExtent.height))) {
593 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
594 "%s() called with pCreateInfo->imageExtent = "
595 "(%d,%d), which is outside the bounds "
596 "returned by vkGetSurfacePropertiesKHR(): "
597 "currentExtent = (%d,%d), minImageExtent = "
598 "(%d,%d), maxImageExtent = (%d,%d).",
599 fn,
600 pCreateInfo->imageExtent.width,
601 pCreateInfo->imageExtent.height,
602 pProps->currentExtent.width,
603 pProps->currentExtent.height,
604 pProps->minImageExtent.width,
605 pProps->minImageExtent.height,
606 pProps->maxImageExtent.width,
607 pProps->maxImageExtent.height);
608 }
609 if ((pProps->currentExtent.width != -1) &&
610 ((pCreateInfo->imageExtent.width != pProps->currentExtent.width) ||
611 (pCreateInfo->imageExtent.height != pProps->currentExtent.height))) {
612 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
613 "%s() called with pCreateInfo->imageExtent = "
614 "(%d,%d), which is not equal to the "
615 "currentExtent = (%d,%d) returned by "
616 "vkGetSurfacePropertiesKHR().",
617 fn,
618 pCreateInfo->imageExtent.width,
619 pCreateInfo->imageExtent.height,
620 pProps->currentExtent.width,
621 pProps->currentExtent.height);
622 }
623 // Validate pCreateInfo->preTransform against
624 // VkSurfacePropertiesKHR::supportedTransforms:
625 if (!((1 << pCreateInfo->preTransform) & pProps->supportedTransforms)) {
626 // This is an error situation; one for which we'd like to give
627 // the developer a helpful, multi-line error message. Build it
628 // up a little at a time, and then log it:
629 std::string errorString = "";
630 char str[1024];
631 // Here's the first part of the message:
632 sprintf(str, "%s() called with a non-supported "
633 "pCreateInfo->preTransform (i.e. %s). "
634 "Supported values are:\n",
635 fn,
636 surfaceTransformStr(pCreateInfo->preTransform));
637 errorString += str;
638 for (int i = VK_SURFACE_TRANSFORM_NONE_KHR ;
639 i < VK_SURFACE_TRANSFORM_INHERIT_KHR ; i++) {
640 // Build up the rest of the message:
641 if ((1 << i) & pProps->supportedTransforms) {
642 const char *newStr =
643 surfaceTransformStr((VkSurfaceTransformKHR) (1 << i));
644 sprintf(str, " %s\n", newStr);
645 errorString += str;
646 }
647 }
648 // Log the message that we've built up:
649 skipCall |= debug_report_log_msg(&mydata.report_data,
650 VK_DBG_REPORT_ERROR_BIT,
651 VK_OBJECT_TYPE_DEVICE,
652 (uint64_t) device,
653 0, 0, LAYER_NAME,
654 errorString.c_str());
655 }
656 // Validate pCreateInfo->imageArraySize against
657 // VkSurfacePropertiesKHR::maxImageArraySize:
658 if (pCreateInfo->imageArraySize <= pProps->maxImageArraySize) {
659 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
660 "%s() called with a non-supported "
661 "pCreateInfo->imageArraySize (i.e. %d). "
662 "Maximum value is %d.",
663 fn,
664 pCreateInfo->imageArraySize,
665 pProps->maxImageArraySize);
666 }
667 // Validate pCreateInfo->imageUsageFlags against
668 // VkSurfacePropertiesKHR::supportedUsageFlags:
669 if (pCreateInfo->imageUsageFlags &&
670 (pCreateInfo->imageUsageFlags !=
671 (pCreateInfo->imageUsageFlags & pProps->supportedUsageFlags))) {
672 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
673 "%s() called with a non-supported "
674 "pCreateInfo->imageUsageFlags (i.e. 0x%08x)."
675 " Supported flag bits are 0x%08x.",
676 fn,
677 pCreateInfo->imageUsageFlags,
678 pProps->supportedUsageFlags);
679 }
680 }
681 if (!pDevice->surfaceFormatCount) {
682 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
683 "%s() called before calling "
684 "vkGetSurfaceFormatsKHR().",
685 fn);
686 } else {
687 // Validate pCreateInfo->imageFormat against
688 // VkSurfaceFormatKHR::format:
689 bool foundFormat = false;
690 bool foundColorSpace = false;
691 bool foundMatch = false;
692 for (int i = 0 ; i < pDevice->surfaceFormatCount ; i++) {
693 if (pCreateInfo->imageFormat == pDevice->pSurfaceFormats[i].format) {
694 // Validate pCreateInfo->imageColorSpace against
695 // VkSurfaceFormatKHR::colorSpace:
696 foundFormat = true;
697 if (pCreateInfo->imageColorSpace == pDevice->pSurfaceFormats[i].colorSpace) {
698 foundMatch = true;
699 break;
700 }
701 } else {
702 if (pCreateInfo->imageColorSpace == pDevice->pSurfaceFormats[i].colorSpace) {
703 foundColorSpace = true;
704 }
705 }
706 }
707 if (!foundMatch) {
708 if (!foundFormat) {
709 if (!foundColorSpace) {
710 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device,
711 "VkDevice",
712 "%s() called with neither a "
713 "supported pCreateInfo->imageFormat "
714 "(i.e. %d) nor a supported "
715 "pCreateInfo->imageColorSpace "
716 "(i.e. %d).",
717 fn,
718 pCreateInfo->imageFormat,
719 pCreateInfo->imageColorSpace);
720 } else {
721 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device,
722 "VkDevice",
723 "%s() called with a non-supported "
724 "pCreateInfo->imageFormat (i.e. %d).",
725 fn, pCreateInfo->imageFormat);
726 }
727 } else if (!foundColorSpace) {
728 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
729 "%s() called with a non-supported "
730 "pCreateInfo->imageColorSpace (i.e. %d).",
731 fn, pCreateInfo->imageColorSpace);
732 }
733 }
734 }
735 if (!pDevice->presentModeCount) {
736 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
737 "%s() called before calling "
738 "vkGetSurfacePresentModesKHR().",
739 fn);
740 } else {
741 // Validate pCreateInfo->presentMode against
742 // vkGetSurfacePresentModesKHR():
743 bool foundMatch = false;
744 for (int i = 0 ; i < pDevice->presentModeCount ; i++) {
745 if (pDevice->pPresentModes[i] == pCreateInfo->presentMode) {
746 foundMatch = true;
747 break;
748 }
749 }
750 if (!foundMatch) {
751 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
752 "%s() called with a non-supported "
753 "pCreateInfo->presentMode (i.e. %s).",
754 fn,
755 presentModeStr(pCreateInfo->presentMode));
756 }
757 }
758
759 // TODO: Validate the following values:
760 // - pCreateInfo->sharingMode
761 // - pCreateInfo->queueFamilyCount
762 // - pCreateInfo->pQueueFamilyIndices
763 // - pCreateInfo->oldSwapchain
764
765 return skipCall;
766}
767
768VK_LAYER_EXPORT VkResult VKAPI vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, VkSwapchainKHR* pSwapchain)
769{
770 VkResult result = VK_SUCCESS;
771 VkBool32 skipCall = validateCreateSwapchainKHR(device, pCreateInfo,
772 pSwapchain);
773
774 if (VK_FALSE == skipCall) {
775 // Call down the call chain:
776 result = device_dispatch_table(device)->CreateSwapchainKHR(
777 device, pCreateInfo, pSwapchain);
778
779 if (result == VK_SUCCESS) {
780 // Remember the swapchain's handle, and link it to the device:
781 SwpDevice *pDevice = &deviceMap[device];
782
783 swapchainMap[pSwapchain->handle].swapchain = *pSwapchain;
784 pDevice->swapchains[pSwapchain->handle] =
785 &swapchainMap[pSwapchain->handle];
786 swapchainMap[pSwapchain->handle].pDevice = pDevice;
787 swapchainMap[pSwapchain->handle].imageCount = 0;
788 }
789
790 return result;
791 }
792 return VK_ERROR_VALIDATION_FAILED;
793}
794
795VK_LAYER_EXPORT VkResult VKAPI vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain)
796{
797 VkBool32 skipCall = VK_FALSE;
798
799 // Validate that a valid VkDevice was used, and that the device
800 // extension was enabled:
801 SwpDevice *pDevice = &deviceMap[device];
802 if (!pDevice) {
803 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
804 device,
805 "VkDevice");
806 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
807 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
808 "%s() called even though the "
809 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
810 "extension was not enabled for this VkDevice.",
811 __FUNCTION__);
812 }
813
814 // Regardless of skipCall value, do some internal cleanup:
815 SwpSwapchain *pSwapchain = &swapchainMap[swapchain.handle];
816 if (pSwapchain) {
817 // Delete the SwpSwapchain associated with this swapchain:
818 if (pSwapchain->pDevice) {
819 pSwapchain->pDevice->swapchains.erase(swapchain.handle);
820 if (device != pSwapchain->pDevice->device) {
821 LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
822 "%s() called with a different VkDevice than the "
823 "VkSwapchainKHR was created with.",
824 __FUNCTION__);
825 }
826 }
827 if (pSwapchain->imageCount) {
828 pSwapchain->images.clear();
829 }
830 swapchainMap.erase(swapchain.handle);
831 } else {
832 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
833 swapchain.handle,
834 "VkSwapchainKHR");
835 }
836
837 if (VK_FALSE == skipCall) {
838 // Call down the call chain:
839 VkResult result = device_dispatch_table(device)->DestroySwapchainKHR(device, swapchain);
840 return result;
841 }
842 return VK_ERROR_VALIDATION_FAILED;
843}
844
845VK_LAYER_EXPORT VkResult VKAPI vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pCount, VkImage* pSwapchainImages)
846{
847 VkResult result = VK_SUCCESS;
848 VkBool32 skipCall = VK_FALSE;
849
850 // Validate that a valid VkDevice was used, and that the device
851 // extension was enabled:
852 SwpDevice *pDevice = &deviceMap[device];
853 if (!pDevice) {
854 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
855 device,
856 "VkDevice");
857 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
858 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
859 "%s() called even though the "
860 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
861 "extension was not enabled for this VkDevice.",
862 __FUNCTION__);
863 }
864 SwpSwapchain *pSwapchain = &swapchainMap[swapchain.handle];
865 if (!pSwapchain) {
866 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
867 swapchain.handle,
868 "VkSwapchainKHR");
869 }
870
871 if (VK_FALSE == skipCall) {
872 // Call down the call chain:
873 result = device_dispatch_table(device)->GetSwapchainImagesKHR(
874 device, swapchain, pCount, pSwapchainImages);
875
876 if ((result == VK_SUCCESS) && pSwapchain &&pSwapchainImages &&
877 pCount && (*pCount > 0)) {
878 // Record the images and their state:
879 if (pSwapchain) {
880 pSwapchain->imageCount = *pCount;
881 for (int i = 0 ; i < *pCount ; i++) {
882 pSwapchain->images[i].image = pSwapchainImages[i];
883 pSwapchain->images[i].pSwapchain = pSwapchain;
884 pSwapchain->images[i].ownedByApp = false;
885 }
886 }
887 }
888
889 return result;
890 }
891 return VK_ERROR_VALIDATION_FAILED;
892}
893
894VK_LAYER_EXPORT VkResult VKAPI vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, uint32_t* pImageIndex)
895{
896// TODO: Record/update the state of the swapchain, in case an error occurs
897// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
898 VkResult result = VK_SUCCESS;
899 VkBool32 skipCall = VK_FALSE;
900
901 // Validate that a valid VkDevice was used, and that the device
902 // extension was enabled:
903 SwpDevice *pDevice = &deviceMap[device];
904 if (!pDevice) {
905 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_DEVICE,
906 device,
907 "VkDevice");
908 } else if (!pDevice->deviceSwapchainExtensionEnabled) {
909 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE, device, "VkDevice",
910 "%s() called even though the "
911 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
912 "extension was not enabled for this VkDevice.",
913 __FUNCTION__);
914 }
915 // Validate that a valid VkSwapchainKHR was used:
916 SwpSwapchain *pSwapchain = &swapchainMap[swapchain.handle];
917 if (!pSwapchain) {
918 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
919 swapchain.handle,
920 "VkSwapchainKHR");
921 } else {
922 // Look to see if the application is trying to own too many images at
923 // the same time (i.e. not leave any to display):
924 int imagesOwnedByApp = 0;
925 for (int i = 0 ; i < pSwapchain->imageCount ; i++) {
926 if (pSwapchain->images[i].ownedByApp) {
927 imagesOwnedByApp++;
928 }
929 }
930 if (imagesOwnedByApp >= (pSwapchain->imageCount - 1)) {
931 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_SWAPCHAIN_KHR, swapchain,
932 "VkSwapchainKHR",
933 "%s() called when the application already "
934 "owns all presentable images in this "
935 "swapchain except for the image currently "
936 "being displayed. This call to %s() cannot "
937 "succeed unless another thread calls the "
938 "vkQueuePresentKHR() function in order to "
939 "release ownership of one of the presentable "
940 "images of this swapchain.",
941 __FUNCTION__, __FUNCTION__);
942 }
943 }
944
945 if (VK_FALSE == skipCall) {
946 // Call down the call chain:
947 result = device_dispatch_table(device)->AcquireNextImageKHR(
948 device, swapchain, timeout, semaphore, pImageIndex);
949
950 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) &&
951 pSwapchain) {
952 if (*pImageIndex >= pSwapchain->imageCount) {
953 LOG_ERROR(VK_OBJECT_TYPE_SWAPCHAIN_KHR, swapchain,
954 "VkSwapchainKHR",
955 "%s() returned an index that's too large (i.e. %d). "
956 "There are only %d images in this VkSwapchainKHR.",
957 __FUNCTION__, *pImageIndex, pSwapchain->imageCount);
958 }
959 if (pSwapchain->images[*pImageIndex].ownedByApp) {
960 LOG_ERROR(VK_OBJECT_TYPE_SWAPCHAIN_KHR, swapchain,
961 "VkSwapchainKHR",
962 "%s() returned an index (i.e. %d) for an image that "
963 "is already owned by the application.\n",
964 __FUNCTION__, *pImageIndex);
965 }
966 // Change the state of the image (now owned by the application):
967 pSwapchain->images[*pImageIndex].ownedByApp = true;
968 }
969
970 return result;
971 }
972 return VK_ERROR_VALIDATION_FAILED;
973}
974
975VK_LAYER_EXPORT VkResult VKAPI vkQueuePresentKHR(VkQueue queue, VkPresentInfoKHR* pPresentInfo)
976{
977// TODOs:
978//
979// - Ensure that the queue is active, and is one of the queueFamilyIndex's
980// that was returned by a previuos query.
981// - Record/update the state of the swapchain, in case an error occurs
982// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
983 VkResult result = VK_SUCCESS;
984 VkBool32 skipCall = VK_FALSE;
985
986 for (int i = 0; i < pPresentInfo->swapchainCount ; i++) {
987 int index = pPresentInfo->imageIndices[i];
988 SwpSwapchain *pSwapchain =
989 &swapchainMap[pPresentInfo->swapchains[i].handle];
990 if (pSwapchain) {
991 if (!pSwapchain->pDevice->deviceSwapchainExtensionEnabled) {
992 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE,
993 pSwapchain->pDevice, "VkDevice",
994 "%s() called even though the "
995 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
996 "extension was not enabled for this "
997 "VkDevice.",
998 __FUNCTION__);
999 }
1000 if (index >= pSwapchain->imageCount) {
1001 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
1002 pPresentInfo->swapchains[i].handle,
1003 "VkSwapchainKHR",
1004 "%s() called for an index that is too "
1005 "large (i.e. %d). There are only %d "
1006 "images in this VkSwapchainKHR.\n",
1007 __FUNCTION__, index,
1008 pSwapchain->imageCount);
1009 } else {
1010 if (!pSwapchain->images[index].ownedByApp) {
1011 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
1012 pPresentInfo->swapchains[i].handle,
1013 "VkSwapchainKHR",
1014 "%s() returned an index (i.e. %d) "
1015 "for an image that is not owned by "
1016 "the application.",
1017 __FUNCTION__, index);
1018 }
1019 }
1020 } else {
1021 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
1022 pPresentInfo->swapchains[i].handle,
1023 "VkSwapchainKHR");
1024 }
1025 }
1026
1027 if (VK_FALSE == skipCall) {
1028 // Call down the call chain:
1029 result = device_dispatch_table(queue)->QueuePresentKHR(queue,
1030 pPresentInfo);
1031
1032 if ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) {
1033 for (int i = 0; i < pPresentInfo->swapchainCount ; i++) {
1034 int index = pPresentInfo->imageIndices[i];
1035 SwpSwapchain *pSwapchain =
1036 &swapchainMap[pPresentInfo->swapchains[i].handle];
1037 if (pSwapchain) {
1038 // Change the state of the image (no longer owned by the
1039 // application):
1040 pSwapchain->images[index].ownedByApp = false;
1041 }
1042 }
1043 }
1044
1045 return result;
1046 }
1047 return VK_ERROR_VALIDATION_FAILED;
1048}
1049
1050static inline PFN_vkVoidFunction layer_intercept_proc(const char *name)
1051{
1052 if (!name || name[0] != 'v' || name[1] != 'k')
1053 return NULL;
1054
1055 name += 2;
1056 if (!strcmp(name, "CreateInstance"))
1057 return (PFN_vkVoidFunction) vkCreateInstance;
1058 if (!strcmp(name, "DestroyInstance"))
1059 return (PFN_vkVoidFunction) vkDestroyInstance;
1060 if (!strcmp(name, "EnumeratePhysicalDevices"))
1061 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
1062 if (!strcmp(name, "CreateDevice"))
1063 return (PFN_vkVoidFunction) vkCreateDevice;
1064 if (!strcmp(name, "DestroyDevice"))
1065 return (PFN_vkVoidFunction) vkDestroyDevice;
1066
1067 return NULL;
1068}
1069static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name)
1070{
1071 if (!name || name[0] != 'v' || name[1] != 'k')
1072 return NULL;
1073
1074 name += 2;
1075 if (!strcmp(name, "CreateInstance"))
1076 return (PFN_vkVoidFunction) vkCreateInstance;
1077 if (!strcmp(name, "DestroyInstance"))
1078 return (PFN_vkVoidFunction) vkDestroyInstance;
1079 if (!strcmp(name, "EnumeratePhysicalDevices"))
1080 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
1081
1082 return NULL;
1083}
1084
1085VK_LAYER_EXPORT VkResult VKAPI vkDbgCreateMsgCallback(VkInstance instance, VkFlags msgFlags, const PFN_vkDbgMsgCallback pfnMsgCallback, void* pUserData, VkDbgMsgCallback* pMsgCallback)
1086{
1087 return layer_create_msg_callback(&mydata.report_data, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
1088}
1089
1090VK_LAYER_EXPORT VkResult VKAPI vkDbgDestroyMsgCallback(VkInstance instance, VkDbgMsgCallback msgCallback)
1091{
1092 layer_destroy_msg_callback(&mydata.report_data, msgCallback);
1093 return VK_SUCCESS;
1094}
1095
1096VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(VkDevice device, const char* funcName)
1097{
1098 PFN_vkVoidFunction addr;
1099 if (device == VK_NULL_HANDLE) {
1100 return NULL;
1101 }
1102 loader_platform_thread_once(&initOnce, initSwapchain);
1103
1104 /* loader uses this to force layer initialization; device object is wrapped */
1105 if (!strcmp("vkGetDeviceProcAddr", funcName)) {
1106 initDeviceTable((const VkBaseLayerObject *) device);
1107 return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
1108 }
1109
1110 addr = layer_intercept_proc(funcName);
1111 if (addr)
1112 return addr;
1113
1114 VkLayerDispatchTable *pDisp = device_dispatch_table(device);
1115 if (deviceMap.size() != 0 &&
1116 deviceMap[pDisp].deviceSwapchainExtensionEnabled)
1117 {
1118 if (!strcmp("vkGetSurfacePropertiesKHR", funcName))
1119 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSurfacePropertiesKHR);
1120 if (!strcmp("vkGetSurfaceFormatsKHR", funcName))
1121 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSurfaceFormatsKHR);
1122 if (!strcmp("vkGetSurfacePresentModesKHR", funcName))
1123 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSurfacePresentModesKHR);
1124 if (!strcmp("vkCreateSwapchainKHR", funcName))
1125 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateSwapchainKHR);
1126 if (!strcmp("vkDestroySwapchainKHR", funcName))
1127 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySwapchainKHR);
1128 if (!strcmp("vkGetSwapchainImagesKHR", funcName))
1129 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSwapchainImagesKHR);
1130 if (!strcmp("vkAcquireNextImageKHR", funcName))
1131 return reinterpret_cast<PFN_vkVoidFunction>(vkAcquireNextImageKHR);
1132 if (!strcmp("vkQueuePresentKHR", funcName))
1133 return reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR);
1134 }
1135 {
1136 if (pDisp->GetDeviceProcAddr == NULL)
1137 return NULL;
1138 return pDisp->GetDeviceProcAddr(device, funcName);
1139 }
1140}
1141
1142VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
1143{
1144 PFN_vkVoidFunction addr;
1145 if (instance == VK_NULL_HANDLE) {
1146 return NULL;
1147 }
1148 loader_platform_thread_once(&initOnce, initSwapchain);
1149
1150 /* loader uses this to force layer initialization; instance object is wrapped */
1151 if (!strcmp("vkGetInstanceProcAddr", funcName)) {
1152 initInstanceTable((const VkBaseLayerObject *) instance);
1153 return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
1154 }
1155
1156 addr = layer_intercept_instance_proc(funcName);
1157 if (addr)
1158 return addr;
1159
1160 VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);
1161 if (instanceMap.size() != 0 &&
1162 instanceMap[instance].swapchainExtensionEnabled)
1163 {
1164 if (!strcmp("vkGetPhysicalDeviceSurfaceSupportKHR", funcName))
1165 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceSupportKHR);
1166 }
1167
1168 if (pTable->GetInstanceProcAddr == NULL)
1169 return NULL;
1170 return pTable->GetInstanceProcAddr(instance, funcName);
1171}
1172