blob: 37864dae97fcccb5efbb213ee10ee4f854a1e42b [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)) {
Ian Elliotte38ed292015-09-24 18:33:16 -0600931 skipCall |= LOG_PERF_WARNING(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
932 swapchain,
933 "VkSwapchainKHR",
934 "%s() called when the application "
935 "already owns all presentable images "
936 "in this swapchain except for the "
937 "image currently being displayed. "
938 "This call to %s() cannot succeed "
939 "unless another thread calls the "
940 "vkQueuePresentKHR() function in "
941 "order to release ownership of one of "
942 "the presentable images of this "
943 "swapchain.",
944 __FUNCTION__, __FUNCTION__);
Ian Elliott329da012015-09-22 10:51:24 -0600945 }
946 }
947
948 if (VK_FALSE == skipCall) {
949 // Call down the call chain:
950 result = device_dispatch_table(device)->AcquireNextImageKHR(
951 device, swapchain, timeout, semaphore, pImageIndex);
952
953 if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) &&
954 pSwapchain) {
955 if (*pImageIndex >= pSwapchain->imageCount) {
956 LOG_ERROR(VK_OBJECT_TYPE_SWAPCHAIN_KHR, swapchain,
957 "VkSwapchainKHR",
958 "%s() returned an index that's too large (i.e. %d). "
959 "There are only %d images in this VkSwapchainKHR.",
960 __FUNCTION__, *pImageIndex, pSwapchain->imageCount);
961 }
962 if (pSwapchain->images[*pImageIndex].ownedByApp) {
963 LOG_ERROR(VK_OBJECT_TYPE_SWAPCHAIN_KHR, swapchain,
964 "VkSwapchainKHR",
965 "%s() returned an index (i.e. %d) for an image that "
966 "is already owned by the application.\n",
967 __FUNCTION__, *pImageIndex);
968 }
969 // Change the state of the image (now owned by the application):
970 pSwapchain->images[*pImageIndex].ownedByApp = true;
971 }
972
973 return result;
974 }
975 return VK_ERROR_VALIDATION_FAILED;
976}
977
978VK_LAYER_EXPORT VkResult VKAPI vkQueuePresentKHR(VkQueue queue, VkPresentInfoKHR* pPresentInfo)
979{
980// TODOs:
981//
982// - Ensure that the queue is active, and is one of the queueFamilyIndex's
983// that was returned by a previuos query.
984// - Record/update the state of the swapchain, in case an error occurs
985// (e.g. VK_ERROR_OUT_OF_DATE_KHR).
986 VkResult result = VK_SUCCESS;
987 VkBool32 skipCall = VK_FALSE;
988
989 for (int i = 0; i < pPresentInfo->swapchainCount ; i++) {
990 int index = pPresentInfo->imageIndices[i];
991 SwpSwapchain *pSwapchain =
992 &swapchainMap[pPresentInfo->swapchains[i].handle];
993 if (pSwapchain) {
994 if (!pSwapchain->pDevice->deviceSwapchainExtensionEnabled) {
995 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_DEVICE,
996 pSwapchain->pDevice, "VkDevice",
997 "%s() called even though the "
998 VK_EXT_KHR_DEVICE_SWAPCHAIN_EXTENSION_NAME,
999 "extension was not enabled for this "
1000 "VkDevice.",
1001 __FUNCTION__);
1002 }
1003 if (index >= pSwapchain->imageCount) {
1004 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
1005 pPresentInfo->swapchains[i].handle,
1006 "VkSwapchainKHR",
1007 "%s() called for an index that is too "
1008 "large (i.e. %d). There are only %d "
1009 "images in this VkSwapchainKHR.\n",
1010 __FUNCTION__, index,
1011 pSwapchain->imageCount);
1012 } else {
1013 if (!pSwapchain->images[index].ownedByApp) {
1014 skipCall |= LOG_ERROR(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
1015 pPresentInfo->swapchains[i].handle,
1016 "VkSwapchainKHR",
1017 "%s() returned an index (i.e. %d) "
1018 "for an image that is not owned by "
1019 "the application.",
1020 __FUNCTION__, index);
1021 }
1022 }
1023 } else {
1024 skipCall |= LOG_ERROR_NON_VALID_OBJ(VK_OBJECT_TYPE_SWAPCHAIN_KHR,
1025 pPresentInfo->swapchains[i].handle,
1026 "VkSwapchainKHR");
1027 }
1028 }
1029
1030 if (VK_FALSE == skipCall) {
1031 // Call down the call chain:
1032 result = device_dispatch_table(queue)->QueuePresentKHR(queue,
1033 pPresentInfo);
1034
1035 if ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) {
1036 for (int i = 0; i < pPresentInfo->swapchainCount ; i++) {
1037 int index = pPresentInfo->imageIndices[i];
1038 SwpSwapchain *pSwapchain =
1039 &swapchainMap[pPresentInfo->swapchains[i].handle];
1040 if (pSwapchain) {
1041 // Change the state of the image (no longer owned by the
1042 // application):
1043 pSwapchain->images[index].ownedByApp = false;
1044 }
1045 }
1046 }
1047
1048 return result;
1049 }
1050 return VK_ERROR_VALIDATION_FAILED;
1051}
1052
1053static inline PFN_vkVoidFunction layer_intercept_proc(const char *name)
1054{
1055 if (!name || name[0] != 'v' || name[1] != 'k')
1056 return NULL;
1057
1058 name += 2;
1059 if (!strcmp(name, "CreateInstance"))
1060 return (PFN_vkVoidFunction) vkCreateInstance;
1061 if (!strcmp(name, "DestroyInstance"))
1062 return (PFN_vkVoidFunction) vkDestroyInstance;
1063 if (!strcmp(name, "EnumeratePhysicalDevices"))
1064 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
1065 if (!strcmp(name, "CreateDevice"))
1066 return (PFN_vkVoidFunction) vkCreateDevice;
1067 if (!strcmp(name, "DestroyDevice"))
1068 return (PFN_vkVoidFunction) vkDestroyDevice;
1069
1070 return NULL;
1071}
1072static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name)
1073{
1074 if (!name || name[0] != 'v' || name[1] != 'k')
1075 return NULL;
1076
1077 name += 2;
1078 if (!strcmp(name, "CreateInstance"))
1079 return (PFN_vkVoidFunction) vkCreateInstance;
1080 if (!strcmp(name, "DestroyInstance"))
1081 return (PFN_vkVoidFunction) vkDestroyInstance;
1082 if (!strcmp(name, "EnumeratePhysicalDevices"))
1083 return (PFN_vkVoidFunction) vkEnumeratePhysicalDevices;
1084
1085 return NULL;
1086}
1087
1088VK_LAYER_EXPORT VkResult VKAPI vkDbgCreateMsgCallback(VkInstance instance, VkFlags msgFlags, const PFN_vkDbgMsgCallback pfnMsgCallback, void* pUserData, VkDbgMsgCallback* pMsgCallback)
1089{
1090 return layer_create_msg_callback(&mydata.report_data, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
1091}
1092
1093VK_LAYER_EXPORT VkResult VKAPI vkDbgDestroyMsgCallback(VkInstance instance, VkDbgMsgCallback msgCallback)
1094{
1095 layer_destroy_msg_callback(&mydata.report_data, msgCallback);
1096 return VK_SUCCESS;
1097}
1098
1099VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(VkDevice device, const char* funcName)
1100{
1101 PFN_vkVoidFunction addr;
1102 if (device == VK_NULL_HANDLE) {
1103 return NULL;
1104 }
1105 loader_platform_thread_once(&initOnce, initSwapchain);
1106
1107 /* loader uses this to force layer initialization; device object is wrapped */
1108 if (!strcmp("vkGetDeviceProcAddr", funcName)) {
1109 initDeviceTable((const VkBaseLayerObject *) device);
1110 return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
1111 }
1112
1113 addr = layer_intercept_proc(funcName);
1114 if (addr)
1115 return addr;
1116
1117 VkLayerDispatchTable *pDisp = device_dispatch_table(device);
1118 if (deviceMap.size() != 0 &&
1119 deviceMap[pDisp].deviceSwapchainExtensionEnabled)
1120 {
1121 if (!strcmp("vkGetSurfacePropertiesKHR", funcName))
1122 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSurfacePropertiesKHR);
1123 if (!strcmp("vkGetSurfaceFormatsKHR", funcName))
1124 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSurfaceFormatsKHR);
1125 if (!strcmp("vkGetSurfacePresentModesKHR", funcName))
1126 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSurfacePresentModesKHR);
1127 if (!strcmp("vkCreateSwapchainKHR", funcName))
1128 return reinterpret_cast<PFN_vkVoidFunction>(vkCreateSwapchainKHR);
1129 if (!strcmp("vkDestroySwapchainKHR", funcName))
1130 return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySwapchainKHR);
1131 if (!strcmp("vkGetSwapchainImagesKHR", funcName))
1132 return reinterpret_cast<PFN_vkVoidFunction>(vkGetSwapchainImagesKHR);
1133 if (!strcmp("vkAcquireNextImageKHR", funcName))
1134 return reinterpret_cast<PFN_vkVoidFunction>(vkAcquireNextImageKHR);
1135 if (!strcmp("vkQueuePresentKHR", funcName))
1136 return reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR);
1137 }
1138 {
1139 if (pDisp->GetDeviceProcAddr == NULL)
1140 return NULL;
1141 return pDisp->GetDeviceProcAddr(device, funcName);
1142 }
1143}
1144
1145VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
1146{
1147 PFN_vkVoidFunction addr;
1148 if (instance == VK_NULL_HANDLE) {
1149 return NULL;
1150 }
1151 loader_platform_thread_once(&initOnce, initSwapchain);
1152
1153 /* loader uses this to force layer initialization; instance object is wrapped */
1154 if (!strcmp("vkGetInstanceProcAddr", funcName)) {
1155 initInstanceTable((const VkBaseLayerObject *) instance);
1156 return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
1157 }
1158
1159 addr = layer_intercept_instance_proc(funcName);
1160 if (addr)
1161 return addr;
1162
1163 VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);
1164 if (instanceMap.size() != 0 &&
1165 instanceMap[instance].swapchainExtensionEnabled)
1166 {
1167 if (!strcmp("vkGetPhysicalDeviceSurfaceSupportKHR", funcName))
1168 return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceSupportKHR);
1169 }
1170
1171 if (pTable->GetInstanceProcAddr == NULL)
1172 return NULL;
1173 return pTable->GetInstanceProcAddr(instance, funcName);
1174}
1175