111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* Copyright (c) 2015-2016 The Khronos Group Inc.
211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Copyright (c) 2015-2016 Valve Corporation
311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Copyright (c) 2015-2016 LunarG, Inc.
411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Copyright (C) 2015-2016 Google Inc.
511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Licensed under the Apache License, Version 2.0 (the "License");
711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * you may not use this file except in compliance with the License.
811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * You may obtain a copy of the License at
911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
1011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *     http://www.apache.org/licenses/LICENSE-2.0
1111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
1211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Unless required by applicable law or agreed to in writing, software
1311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * distributed under the License is distributed on an "AS IS" BASIS,
1411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * See the License for the specific language governing permissions and
1611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * limitations under the License.
1711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
1811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Ian Elliott <ian@lunarg.com>
1911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Ian Elliott <ianelliott@google.com>
2011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */
2111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
2211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <mutex>
2311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <stdio.h>
2411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <string.h>
2511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <vk_loader_platform.h>
2611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <vulkan/vk_icd.h>
2711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "swapchain.h"
2811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_layer_extension_utils.h"
2911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_enum_string_helper.h"
3011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_layer_utils.h"
3111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
3211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertnamespace swapchain {
3311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
3411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic std::mutex global_lock;
3511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
3611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// The following is for logging error messages:
3711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic std::unordered_map<void *, layer_data *> layer_data_map;
3811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
3911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
4011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
4111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic const VkLayerProperties swapchain_layer = {
4211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    "VK_LAYER_LUNARG_swapchain", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer",
4311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
4411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
4511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void createDeviceRegisterExtensions(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
4611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                           VkDevice device) {
4711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uint32_t i;
4811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
5011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
5111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkLayerDispatchTable *pDisp = my_device_data->device_dispatch_table;
5211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr;
5311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
5411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR)gpa(device, "vkCreateSwapchainKHR");
5511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->DestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)gpa(device, "vkDestroySwapchainKHR");
5611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)gpa(device, "vkGetSwapchainImagesKHR");
5711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)gpa(device, "vkAcquireNextImageKHR");
5811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR)gpa(device, "vkQueuePresentKHR");
5911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->GetDeviceQueue = (PFN_vkGetDeviceQueue)gpa(device, "vkGetDeviceQueue");
6011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
6111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpPhysicalDevice *pPhysicalDevice = NULL;
6211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
6311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_instance_data->physicalDeviceMap.find(physicalDevice);
6411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pPhysicalDevice = (it == my_instance_data->physicalDeviceMap.end()) ? NULL : &it->second;
6511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
6611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pPhysicalDevice) {
6711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        my_device_data->deviceMap[device].pPhysicalDevice = pPhysicalDevice;
6811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pPhysicalDevice->pDevice = &my_device_data->deviceMap[device];
6911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
7011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // TBD: Should we leave error in (since Swapchain really needs this
7111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // link)?
7211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        log_msg(my_instance_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
7311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                (uint64_t)physicalDevice, __LINE__, SWAPCHAIN_INVALID_HANDLE, "Swapchain",
7411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                "vkCreateDevice() called with a non-valid VkPhysicalDevice.");
7511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
7611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_device_data->deviceMap[device].device = device;
7711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_device_data->deviceMap[device].swapchainExtensionEnabled = false;
7811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
7911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Record whether the WSI device extension was enabled for this VkDevice.
8011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // No need to check if the extension was advertised by
8111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // vkEnumerateDeviceExtensionProperties(), since the loader handles that.
8211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
8311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0) {
8411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_device_data->deviceMap[device].swapchainExtensionEnabled = true;
8611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
8711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
8811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
8911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
9011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void createInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreateInfo, VkInstance instance) {
9111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uint32_t i;
9211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
9311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkLayerInstanceDispatchTable *pDisp = my_data->instance_dispatch_table;
9411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    PFN_vkGetInstanceProcAddr gpa = pDisp->GetInstanceProcAddr;
9511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_ANDROID_KHR
9611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->CreateAndroidSurfaceKHR = (PFN_vkCreateAndroidSurfaceKHR)gpa(instance, "vkCreateAndroidSurfaceKHR");
9711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_ANDROID_KHR
9811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_MIR_KHR
9911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->CreateMirSurfaceKHR = (PFN_vkCreateMirSurfaceKHR)gpa(instance, "vkCreateMirSurfaceKHR");
10011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->GetPhysicalDeviceMirPresentationSupportKHR =
10111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        (PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
10211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_MIR_KHR
10311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_WAYLAND_KHR
10411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->CreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR)gpa(instance, "vkCreateWaylandSurfaceKHR");
10511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->GetPhysicalDeviceWaylandPresentationSupportKHR =
10611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
10711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_WAYLAND_KHR
10811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_WIN32_KHR
10911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->CreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)gpa(instance, "vkCreateWin32SurfaceKHR");
11011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->GetPhysicalDeviceWin32PresentationSupportKHR =
11111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
11211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_WIN32_KHR
11311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_XCB_KHR
11411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->CreateXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR)gpa(instance, "vkCreateXcbSurfaceKHR");
11511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->GetPhysicalDeviceXcbPresentationSupportKHR =
11611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
11711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_XCB_KHR
11811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_XLIB_KHR
11911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->CreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR)gpa(instance, "vkCreateXlibSurfaceKHR");
12011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->GetPhysicalDeviceXlibPresentationSupportKHR =
12111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)gpa(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
12211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_XLIB_KHR
12311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->DestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)gpa(instance, "vkDestroySurfaceKHR");
12411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->GetPhysicalDeviceSurfaceSupportKHR =
12511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        (PFN_vkGetPhysicalDeviceSurfaceSupportKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceSupportKHR");
12611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->GetPhysicalDeviceSurfaceCapabilitiesKHR =
12711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
12811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->GetPhysicalDeviceSurfaceFormatsKHR =
12911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)gpa(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR");
13011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pDisp->GetPhysicalDeviceSurfacePresentModesKHR =
13111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)gpa(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR");
13211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
13311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Remember this instance, and whether the VK_KHR_surface extension
13411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // was enabled for it:
13511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instanceMap[instance].instance = instance;
13611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instanceMap[instance].surfaceExtensionEnabled = false;
13711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_ANDROID_KHR
13811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instanceMap[instance].androidSurfaceExtensionEnabled = false;
13911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_ANDROID_KHR
14011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_MIR_KHR
14111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instanceMap[instance].mirSurfaceExtensionEnabled = false;
14211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_MIR_KHR
14311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_WAYLAND_KHR
14411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instanceMap[instance].waylandSurfaceExtensionEnabled = false;
14511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_WAYLAND_KHR
14611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_WIN32_KHR
14711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instanceMap[instance].win32SurfaceExtensionEnabled = false;
14811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_WIN32_KHR
14911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_XCB_KHR
15011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = false;
15111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_XCB_KHR
15211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_XLIB_KHR
15311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = false;
15411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_XLIB_KHR
15511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
15611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Look for one or more debug report create info structures, and copy the
15711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // callback(s) for each one found (for use by vkDestroyInstance)
15811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_copy_tmp_callbacks(pCreateInfo->pNext, &my_data->num_tmp_callbacks, &my_data->tmp_dbg_create_infos,
15911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             &my_data->tmp_callbacks);
16011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
16111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Record whether the WSI instance extension was enabled for this
16211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // VkInstance.  No need to check if the extension was advertised by
16311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // vkEnumerateInstanceExtensionProperties(), since the loader handles that.
16411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
16511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SURFACE_EXTENSION_NAME) == 0) {
16611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
16711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->instanceMap[instance].surfaceExtensionEnabled = true;
16811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
16911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_ANDROID_KHR
17011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_ANDROID_SURFACE_EXTENSION_NAME) == 0) {
17111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
17211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->instanceMap[instance].androidSurfaceExtensionEnabled = true;
17311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
17411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_ANDROID_KHR
17511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_MIR_KHR
17611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_MIR_SURFACE_EXTENSION_NAME) == 0) {
17711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
17811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->instanceMap[instance].mirSurfaceExtensionEnabled = true;
17911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
18011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_MIR_KHR
18111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_WAYLAND_KHR
18211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME) == 0) {
18311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
18411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->instanceMap[instance].waylandSurfaceExtensionEnabled = true;
18511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
18611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_WAYLAND_KHR
18711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_WIN32_KHR
18811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_WIN32_SURFACE_EXTENSION_NAME) == 0) {
18911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
19011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->instanceMap[instance].win32SurfaceExtensionEnabled = true;
19111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
19211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_WIN32_KHR
19311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_XCB_KHR
19411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XCB_SURFACE_EXTENSION_NAME) == 0) {
19511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
19611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->instanceMap[instance].xcbSurfaceExtensionEnabled = true;
19711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
19811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_XCB_KHR
19911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_XLIB_KHR
20011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_XLIB_SURFACE_EXTENSION_NAME) == 0) {
20111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
20211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->instanceMap[instance].xlibSurfaceExtensionEnabled = true;
20311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
20411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_XLIB_KHR
20511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
20611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
20711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
20811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_dispatch_table_helper.h"
20911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void init_swapchain(layer_data *my_data, const VkAllocationCallbacks *pAllocator) {
21011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
21111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_swapchain");
21211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
21311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
21411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic const char *surfaceTransformStr(VkSurfaceTransformFlagBitsKHR value) {
21511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Return a string corresponding to the value:
21611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return string_VkSurfaceTransformFlagBitsKHR(value);
21711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
21811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
21911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic const char *surfaceCompositeAlphaStr(VkCompositeAlphaFlagBitsKHR value) {
22011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Return a string corresponding to the value:
22111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return string_VkCompositeAlphaFlagBitsKHR(value);
22211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
22311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
22411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic const char *presentModeStr(VkPresentModeKHR value) {
22511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Return a string corresponding to the value:
22611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return string_VkPresentModeKHR(value);
22711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
22811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
22911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic const char *sharingModeStr(VkSharingMode value) {
23011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Return a string corresponding to the value:
23111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return string_VkSharingMode(value);
23211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
23311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
23411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
23511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
23611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
23711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
23811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(chain_info->u.pLayerInfo);
23911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
24011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
24111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (fpCreateInstance == NULL) {
24211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return VK_ERROR_INITIALIZATION_FAILED;
24311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
24411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
24511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Advance the link info for the next element on the chain
24611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
24711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
24811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
24911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (result != VK_SUCCESS) {
25011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
25111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
25211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
25311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
25411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instance = *pInstance;
25511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
25611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
25711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
25811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->report_data = debug_report_create_instance(my_data->instance_dispatch_table, *pInstance,
25911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                        pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
26011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
26111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Call the following function after my_data is initialized:
26211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    createInstanceRegisterExtensions(pCreateInfo, *pInstance);
26311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    init_swapchain(my_data, pAllocator);
26411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
26511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return result;
26611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
26711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
26811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
26911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    dispatch_key key = get_dispatch_key(instance);
27011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(key, layer_data_map);
27111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpInstance *pInstance = NULL;
27211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
27311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->instanceMap.find(instance);
27411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
27511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
27611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
27711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Call down the call chain:
27811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instance_dispatch_table->DestroyInstance(instance, pAllocator);
27911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
28011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::lock_guard<std::mutex> lock(global_lock);
28111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
28211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Enable the temporary callback(s) here to catch cleanup issues:
28311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool callback_setup = false;
28411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (my_data->num_tmp_callbacks > 0) {
28511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!layer_enable_tmp_callbacks(my_data->report_data, my_data->num_tmp_callbacks, my_data->tmp_dbg_create_infos,
28611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        my_data->tmp_callbacks)) {
28711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            callback_setup = true;
28811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
28911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
29011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
29111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Do additional internal cleanup:
29211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pInstance) {
29311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Delete all of the SwpPhysicalDevice's, SwpSurface's, and the
29411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // SwpInstance associated with this instance:
29511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for (auto it = pInstance->physicalDevices.begin(); it != pInstance->physicalDevices.end(); it++) {
29611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
29711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Free memory that was allocated for/by this SwpPhysicalDevice:
29811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            SwpPhysicalDevice *pPhysicalDevice = it->second;
29911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (pPhysicalDevice) {
30011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if (pPhysicalDevice->pDevice) {
30111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
30211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called before all of its associated "
30311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "VkDevices were destroyed.",
30411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              __FUNCTION__);
30511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
30611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                free(pPhysicalDevice->pSurfaceFormats);
30711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                free(pPhysicalDevice->pPresentModes);
30811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
30911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
31011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Erase the SwpPhysicalDevice's from the my_data->physicalDeviceMap (which
31111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // are simply pointed to by the SwpInstance):
31211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->physicalDeviceMap.erase(it->second->physicalDevice);
31311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
31411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for (auto it = pInstance->surfaces.begin(); it != pInstance->surfaces.end(); it++) {
31511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
31611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Free memory that was allocated for/by this SwpPhysicalDevice:
31711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            SwpSurface *pSurface = it->second;
31811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (pSurface) {
31911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
32011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                          "%s() called before all of its associated "
32111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                          "VkSurfaceKHRs were destroyed.",
32211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                          __FUNCTION__);
32311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
32411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
32511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        my_data->instanceMap.erase(instance);
32611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
32711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
32811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Disable and cleanup the temporary callback(s):
32911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (callback_setup) {
33011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        layer_disable_tmp_callbacks(my_data->report_data, my_data->num_tmp_callbacks, my_data->tmp_callbacks);
33111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
33211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (my_data->num_tmp_callbacks > 0) {
33311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        layer_free_tmp_callbacks(my_data->tmp_dbg_create_infos, my_data->tmp_callbacks);
33411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        my_data->num_tmp_callbacks = 0;
33511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
33611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
33711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Clean up logging callback, if any
33811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    while (my_data->logging_callback.size() > 0) {
33911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
34011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
34111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        my_data->logging_callback.pop_back();
34211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
34311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_debug_report_destroy_instance(my_data->report_data);
34411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
34511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    delete my_data->instance_dispatch_table;
34611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data_map.erase(key);
34711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
34811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
34911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
35011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount,
35111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                       VkQueueFamilyProperties *pQueueFamilyProperties) {
35211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
35311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
35411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Call down the call chain:
35511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instance_dispatch_table->GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount,
35611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                             pQueueFamilyProperties);
35711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
35811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Record the result of this query:
35911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::lock_guard<std::mutex> lock(global_lock);
36011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpPhysicalDevice *pPhysicalDevice = NULL;
36111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
36211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->physicalDeviceMap.find(physicalDevice);
36311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
36411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
36511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pPhysicalDevice && pQueueFamilyPropertyCount && !pQueueFamilyProperties) {
36611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pPhysicalDevice->gotQueueFamilyPropertyCount = true;
36711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pPhysicalDevice->numOfQueueFamilies = *pQueueFamilyPropertyCount;
36811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
36911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
37011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
37111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_ANDROID_KHR
37211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
37311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo,
37411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
37511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = VK_SUCCESS;
37611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
37711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
37811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
37911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpInstance *pInstance = NULL;
38011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
38111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->instanceMap.find(instance);
38211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
38311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
38411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
38511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the platform extension was enabled:
38611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pInstance && !pInstance->androidSurfaceExtensionEnabled) {
38711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
38811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
38911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
39011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
39111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
39211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pCreateInfo) {
39311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
39411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
39511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pCreateInfo->sType != VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR) {
39611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
39711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                              "VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR");
39811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
39911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pCreateInfo->pNext != NULL) {
40011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
40111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
40211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
40311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
40411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
40511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
40611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.unlock();
40711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->instance_dispatch_table->CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
40811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.lock();
40911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
41011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Obtain this pointer again after locking:
41111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
41211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            auto it = my_data->instanceMap.find(instance);
41311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
41411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
41511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((result == VK_SUCCESS) && pInstance && pSurface) {
41611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Record the VkSurfaceKHR returned by the ICD:
41711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].surface = *pSurface;
41811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].pInstance = pInstance;
41911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
42011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
42111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
42211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Point to the associated SwpInstance:
42311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
42411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
42511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
42611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
42711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return VK_ERROR_VALIDATION_FAILED_EXT;
42811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
42911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_ANDROID_KHR
43011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
43111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_MIR_KHR
43211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
43311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateMirSurfaceKHR(VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
43411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    VkSurfaceKHR *pSurface) {
43511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = VK_SUCCESS;
43611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
43711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
43811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
43911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpInstance *pInstance = NULL;
44011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
44111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->instanceMap.find(instance);
44211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
44311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
44411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
44511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the platform extension was enabled:
44611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pInstance && !pInstance->mirSurfaceExtensionEnabled) {
44711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
44811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
44911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_MIR_SURFACE_EXTENSION_NAME);
45011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
45111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
45211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pCreateInfo) {
45311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
45411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
45511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pCreateInfo->sType != VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR) {
45611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
45711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                              "VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR");
45811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
45911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pCreateInfo->pNext != NULL) {
46011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
46111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
46211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
46311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
46411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
46511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
46611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.unlock();
46711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->instance_dispatch_table->CreateMirSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
46811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.lock();
46911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
47011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Obtain this pointer again after locking:
47111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
47211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            auto it = my_data->instanceMap.find(instance);
47311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
47411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
47511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((result == VK_SUCCESS) && pInstance && pSurface) {
47611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Record the VkSurfaceKHR returned by the ICD:
47711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].surface = *pSurface;
47811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].pInstance = pInstance;
47911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
48011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
48111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
48211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Point to the associated SwpInstance:
48311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
48411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
48511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
48611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
48711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return VK_ERROR_VALIDATION_FAILED_EXT;
48811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
48911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
49011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceMirPresentationSupportKHR(VkPhysicalDevice physicalDevice,
49111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                          uint32_t queueFamilyIndex,
49211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                          MirConnection *connection) {
49311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkBool32 result = VK_FALSE;
49411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
49511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
49611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
49711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpPhysicalDevice *pPhysicalDevice = NULL;
49811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
49911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->physicalDeviceMap.find(physicalDevice);
50011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
50111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
50211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
50311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the platform extension was enabled:
50411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->mirSurfaceExtensionEnabled) {
50511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
50611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
50711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
50811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_MIR_SURFACE_EXTENSION_NAME);
50911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
51011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
51111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |=
51211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
51311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                   "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
51411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
51511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    lock.unlock();
51611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
51711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
51811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
51911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->instance_dispatch_table->GetPhysicalDeviceMirPresentationSupportKHR(physicalDevice, queueFamilyIndex,
52011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                              connection);
52111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
52211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return result;
52311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
52411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_MIR_KHR
52511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
52611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_WAYLAND_KHR
52711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
52811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
52911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
53011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = VK_SUCCESS;
53111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
53211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
53311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
53411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpInstance *pInstance = NULL;
53511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
53611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->instanceMap.find(instance);
53711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
53811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
53911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
54011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the platform extension was enabled:
54111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pInstance && !pInstance->waylandSurfaceExtensionEnabled) {
54211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
54311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
54411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
54511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
54611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
54711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pCreateInfo) {
54811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
54911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
55011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR) {
55111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
55211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                              "VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR");
55311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
55411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pCreateInfo->pNext != NULL) {
55511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
55611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
55711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
55811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
55911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
56011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
56111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.unlock();
56211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->instance_dispatch_table->CreateWaylandSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
56311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.lock();
56411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
56511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Obtain this pointer again after locking:
56611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
56711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            auto it = my_data->instanceMap.find(instance);
56811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
56911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
57011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((result == VK_SUCCESS) && pInstance && pSurface) {
57111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Record the VkSurfaceKHR returned by the ICD:
57211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].surface = *pSurface;
57311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].pInstance = pInstance;
57411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
57511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
57611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
57711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Point to the associated SwpInstance:
57811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
57911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
58011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
58111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
58211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return VK_ERROR_VALIDATION_FAILED_EXT;
58311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
58411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
58511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,
58611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                              uint32_t queueFamilyIndex,
58711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                              struct wl_display *display) {
58811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkBool32 result = VK_FALSE;
58911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
59011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
59111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
59211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpPhysicalDevice *pPhysicalDevice = NULL;
59311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
59411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->physicalDeviceMap.find(physicalDevice);
59511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
59611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
59711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
59811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the platform extension was enabled:
59911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->waylandSurfaceExtensionEnabled) {
60011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
60111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
60211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
60311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
60411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
60511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
60611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |=
60711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
60811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                   "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
60911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
61011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    lock.unlock();
61111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
61211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
61311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
61411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->instance_dispatch_table->GetPhysicalDeviceWaylandPresentationSupportKHR(physicalDevice, queueFamilyIndex,
61511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                                  display);
61611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
61711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return result;
61811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
61911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_WAYLAND_KHR
62011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
62111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_WIN32_KHR
62211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
62311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
62411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
62511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = VK_SUCCESS;
62611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
62711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
62811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
62911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpInstance *pInstance = NULL;
63011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
63111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->instanceMap.find(instance);
63211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
63311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
63411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
63511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the platform extension was enabled:
63611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pInstance && !pInstance->win32SurfaceExtensionEnabled) {
63711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
63811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
63911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
64011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
64111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
64211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pCreateInfo) {
64311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
64411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
64511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pCreateInfo->sType != VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR) {
64611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
64711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                              "VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR");
64811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
64911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pCreateInfo->pNext != NULL) {
65011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
65111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
65211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
65311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
65411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
65511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
65611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.unlock();
65711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->instance_dispatch_table->CreateWin32SurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
65811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.lock();
65911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
66011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Obtain this pointer again after locking:
66111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
66211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            auto it = my_data->instanceMap.find(instance);
66311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
66411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
66511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((result == VK_SUCCESS) && pInstance && pSurface) {
66611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Record the VkSurfaceKHR returned by the ICD:
66711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].surface = *pSurface;
66811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].pInstance = pInstance;
66911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
67011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
67111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
67211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Point to the associated SwpInstance:
67311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
67411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
67511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
67611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
67711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return VK_ERROR_VALIDATION_FAILED_EXT;
67811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
67911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
68011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkBool32 VKAPI_CALL
68111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex) {
68211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkBool32 result = VK_FALSE;
68311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
68411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
68511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
68611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpPhysicalDevice *pPhysicalDevice = NULL;
68711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
68811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->physicalDeviceMap.find(physicalDevice);
68911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
69011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
69111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
69211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the platform extension was enabled:
69311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->win32SurfaceExtensionEnabled) {
69411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
69511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
69611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
69711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
69811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
69911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
70011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |=
70111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
70211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                   "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
70311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
70411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    lock.unlock();
70511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
70611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
70711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
70811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->instance_dispatch_table->GetPhysicalDeviceWin32PresentationSupportKHR(physicalDevice, queueFamilyIndex);
70911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
71011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return result;
71111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
71211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_WIN32_KHR
71311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
71411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_XCB_KHR
71511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
71611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
71711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      VkSurfaceKHR *pSurface) {
71811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = VK_SUCCESS;
71911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
72011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
72111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
72211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpInstance *pInstance = NULL;
72311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
72411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->instanceMap.find(instance);
72511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
72611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
72711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
72811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the platform extension was enabled:
72911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pInstance && !pInstance->xcbSurfaceExtensionEnabled) {
73011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
73111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
73211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_XCB_SURFACE_EXTENSION_NAME);
73311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
73411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
73511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pCreateInfo) {
73611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
73711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
73811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR) {
73911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
74011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                              "VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR");
74111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
74211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pCreateInfo->pNext != NULL) {
74311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
74411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
74511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
74611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
74711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
74811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
74911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.unlock();
75011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->instance_dispatch_table->CreateXcbSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
75111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.lock();
75211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
75311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Obtain this pointer again after locking:
75411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
75511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            auto it = my_data->instanceMap.find(instance);
75611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
75711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
75811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((result == VK_SUCCESS) && pInstance && pSurface) {
75911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Record the VkSurfaceKHR returned by the ICD:
76011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].surface = *pSurface;
76111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].pInstance = pInstance;
76211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
76311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
76411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
76511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Point to the associated SwpInstance:
76611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
76711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
76811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
76911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
77011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return VK_ERROR_VALIDATION_FAILED_EXT;
77111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
77211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
77311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkBool32 VKAPI_CALL
77411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex,
77511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                           xcb_connection_t *connection, xcb_visualid_t visual_id) {
77611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkBool32 result = VK_FALSE;
77711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
77811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
77911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
78011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpPhysicalDevice *pPhysicalDevice = NULL;
78111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
78211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->physicalDeviceMap.find(physicalDevice);
78311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
78411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
78511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
78611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the platform extension was enabled:
78711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->xcbSurfaceExtensionEnabled) {
78811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
78911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
79011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
79111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_XCB_SURFACE_EXTENSION_NAME);
79211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
79311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
79411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |=
79511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
79611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                   "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
79711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
79811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    lock.unlock();
79911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
80011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
80111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
80211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->instance_dispatch_table->GetPhysicalDeviceXcbPresentationSupportKHR(physicalDevice, queueFamilyIndex,
80311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                              connection, visual_id);
80411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
80511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return result;
80611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
80711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_XCB_KHR
80811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
80911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_XLIB_KHR
81011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
81111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator,
81211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                     VkSurfaceKHR *pSurface) {
81311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = VK_SUCCESS;
81411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
81511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
81611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
81711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpInstance *pInstance = NULL;
81811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
81911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->instanceMap.find(instance);
82011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
82111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
82211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
82311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the platform extension was enabled:
82411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pInstance && !pInstance->xlibSurfaceExtensionEnabled) {
82511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
82611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
82711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
82811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
82911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
83011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pCreateInfo) {
83111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
83211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
83311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pCreateInfo->sType != VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR) {
83411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
83511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                              "VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR");
83611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
83711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pCreateInfo->pNext != NULL) {
83811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
83911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
84011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
84111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
84211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
84311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
84411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.unlock();
84511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->instance_dispatch_table->CreateXlibSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
84611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.lock();
84711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
84811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Obtain this pointer again after locking:
84911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
85011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            auto it = my_data->instanceMap.find(instance);
85111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
85211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
85311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((result == VK_SUCCESS) && pInstance && pSurface) {
85411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Record the VkSurfaceKHR returned by the ICD:
85511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].surface = *pSurface;
85611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].pInstance = pInstance;
85711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].usedAllocatorToCreate = (pAllocator != NULL);
85811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].numQueueFamilyIndexSupport = 0;
85911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->surfaceMap[*pSurface].pQueueFamilyIndexSupport = NULL;
86011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Point to the associated SwpInstance:
86111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pInstance->surfaces[*pSurface] = &my_data->surfaceMap[*pSurface];
86211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
86311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
86411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
86511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return VK_ERROR_VALIDATION_FAILED_EXT;
86611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
86711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
86811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkBool32 VKAPI_CALL GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
86911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                           uint32_t queueFamilyIndex,
87011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                           Display *dpy, VisualID visualID) {
87111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkBool32 result = VK_FALSE;
87211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
87311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
87411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
87511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpPhysicalDevice *pPhysicalDevice = NULL;
87611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
87711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->physicalDeviceMap.find(physicalDevice);
87811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
87911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
88011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
88111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the platform extension was enabled:
88211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->xlibSurfaceExtensionEnabled) {
88311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
88411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
88511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
88611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
88711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
88811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
88911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |=
89011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
89111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                   "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
89211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
89311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    lock.unlock();
89411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
89511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
89611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
89711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->instance_dispatch_table->GetPhysicalDeviceXlibPresentationSupportKHR(physicalDevice, queueFamilyIndex,
89811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                               dpy, visualID);
89911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
90011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return result;
90111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
90211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_XLIB_KHR
90311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
90411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
90511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) {
90611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
90711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
90811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
90911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpSurface *pSurface = NULL;
91011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
91111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->surfaceMap.find(surface);
91211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pSurface = (it == my_data->surfaceMap.end()) ? NULL : &it->second;
91311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
91411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpInstance *pInstance = NULL;
91511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
91611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->instanceMap.find(instance);
91711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
91811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
91911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
92011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the platform extension was enabled:
92111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pInstance && !pInstance->surfaceExtensionEnabled) {
92211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pInstance, "VkInstance", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
92311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
92411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_SURFACE_EXTENSION_NAME);
92511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
92611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
92711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Regardless of skipCall value, do some internal cleanup:
92811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pSurface) {
92911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Delete the SwpSurface associated with this surface:
93011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pSurface->pInstance) {
93111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pSurface->pInstance->surfaces.erase(surface);
93211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
93311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!pSurface->swapchains.empty()) {
93411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
93511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      "%s() called before all of its associated "
93611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      "VkSwapchainKHRs were destroyed.",
93711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      __FUNCTION__);
93811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Empty and then delete all SwpSwapchain's
93911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            for (auto it = pSurface->swapchains.begin(); it != pSurface->swapchains.end(); it++) {
94011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // Delete all SwpImage's
94111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                it->second->images.clear();
94211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // In case the swapchain's device hasn't been destroyed yet
94311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // (which isn't likely, but is possible), delete its
94411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // association with this swapchain (i.e. so we can't point to
94511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // this swpchain from that device, later on):
94611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if (it->second->pDevice) {
94711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    it->second->pDevice->swapchains.clear();
94811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
94911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
95011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pSurface->swapchains.clear();
95111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
95211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((pAllocator != NULL) != pSurface->usedAllocatorToCreate) {
95311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
95411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      "%s() called with incompatible pAllocator from when "
95511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      "the object was created.",
95611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      __FUNCTION__);
95711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
95811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        my_data->surfaceMap.erase(surface);
95911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
96011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    lock.unlock();
96111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
96211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
96311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
96411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        my_data->instance_dispatch_table->DestroySurfaceKHR(instance, surface, pAllocator);
96511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
96611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
96711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
96811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
96911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) {
97011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = VK_SUCCESS;
97111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
97211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
97311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Call down the call chain:
97411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    result = my_data->instance_dispatch_table->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
97511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
97611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::lock_guard<std::mutex> lock(global_lock);
97711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpInstance *pInstance = NULL;
97811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
97911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->instanceMap.find(instance);
98011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pInstance = (it == my_data->instanceMap.end()) ? NULL : &it->second;
98111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
98211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if ((result == VK_SUCCESS) && pInstance && pPhysicalDevices && (*pPhysicalDeviceCount > 0)) {
98311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Record the VkPhysicalDevices returned by the ICD:
98411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
98511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->physicalDeviceMap[pPhysicalDevices[i]].physicalDevice = pPhysicalDevices[i];
98611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->physicalDeviceMap[pPhysicalDevices[i]].pInstance = pInstance;
98711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->physicalDeviceMap[pPhysicalDevices[i]].pDevice = NULL;
98811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->physicalDeviceMap[pPhysicalDevices[i]].gotQueueFamilyPropertyCount = false;
98911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->physicalDeviceMap[pPhysicalDevices[i]].gotSurfaceCapabilities = false;
99011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->physicalDeviceMap[pPhysicalDevices[i]].surfaceFormatCount = 0;
99111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->physicalDeviceMap[pPhysicalDevices[i]].pSurfaceFormats = NULL;
99211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->physicalDeviceMap[pPhysicalDevices[i]].presentModeCount = 0;
99311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->physicalDeviceMap[pPhysicalDevices[i]].pPresentModes = NULL;
99411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Point to the associated SwpInstance:
99511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (pInstance) {
99611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pInstance->physicalDevices[pPhysicalDevices[i]] = &my_data->physicalDeviceMap[pPhysicalDevices[i]];
99711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
99811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
99911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
100011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return result;
100111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
100211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
100311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice physicalDevice,
100411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                            const VkDeviceCreateInfo *pCreateInfo,
100511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                            const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
100611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
100711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
100811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
100911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(chain_info->u.pLayerInfo);
101011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
101111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
101211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice");
101311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (fpCreateDevice == NULL) {
101411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return VK_ERROR_INITIALIZATION_FAILED;
101511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
101611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
101711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Advance the link info for the next element on the chain
101811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
101911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
102011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
102111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (result != VK_SUCCESS) {
102211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
102311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
102411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
102511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::lock_guard<std::mutex> lock(global_lock);
102611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
102711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
102811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Setup device dispatch table
102911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_device_data->device_dispatch_table = new VkLayerDispatchTable;
103011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
103111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
103211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
103311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    createDeviceRegisterExtensions(physicalDevice, pCreateInfo, *pDevice);
103411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
103511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return result;
103611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
103711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
103811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
103911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    dispatch_key key = get_dispatch_key(device);
104011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(key, layer_data_map);
104111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
104211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Call down the call chain:
104311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
104411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
104511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Do some internal cleanup:
104611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::lock_guard<std::mutex> lock(global_lock);
104711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpDevice *pDevice = NULL;
104811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
104911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->deviceMap.find(device);
105011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
105111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
105211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pDevice) {
105311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Delete the SwpDevice associated with this device:
105411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pDevice->pPhysicalDevice) {
105511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pDevice->pPhysicalDevice->pDevice = NULL;
105611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
105711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!pDevice->swapchains.empty()) {
105811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DEL_OBJECT_BEFORE_CHILDREN,
105911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      "%s() called before all of its associated "
106011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      "VkSwapchainKHRs were destroyed.",
106111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      __FUNCTION__);
106211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Empty and then delete all SwpSwapchain's
106311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            for (auto it = pDevice->swapchains.begin(); it != pDevice->swapchains.end(); it++) {
106411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // Delete all SwpImage's
106511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                it->second->images.clear();
106611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // In case the swapchain's surface hasn't been destroyed yet
106711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // (which is likely) delete its association with this swapchain
106811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // (i.e. so we can't point to this swpchain from that surface,
106911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // later on):
107011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if (it->second->pSurface) {
107111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    it->second->pSurface->swapchains.clear();
107211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
107311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
107411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pDevice->swapchains.clear();
107511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
107611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        my_data->deviceMap.erase(device);
107711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
107811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    delete my_data->device_dispatch_table;
107911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data_map.erase(key);
108011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
108111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
108211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
108311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                  uint32_t queueFamilyIndex, VkSurfaceKHR surface,
108411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                  VkBool32 *pSupported) {
108511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = VK_SUCCESS;
108611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
108711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
108811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
108911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpPhysicalDevice *pPhysicalDevice = NULL;
109011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
109111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->physicalDeviceMap.find(physicalDevice);
109211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
109311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
109411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
109511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the surface extension was enabled:
109611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
109711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
109811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
109911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
110011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_SURFACE_EXTENSION_NAME);
110111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
110211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pPhysicalDevice->gotQueueFamilyPropertyCount) {
110311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice, "VkPhysicalDevice",
110411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              SWAPCHAIN_DID_NOT_QUERY_QUEUE_FAMILIES, "%s() called before calling the "
110511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                      "vkGetPhysicalDeviceQueueFamilyProperties "
110611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                      "function.",
110711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              __FUNCTION__);
110811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else if (pPhysicalDevice->gotQueueFamilyPropertyCount && (queueFamilyIndex >= pPhysicalDevice->numOfQueueFamilies)) {
110911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |=
111011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
111111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                   "VkPhysicalDevice", queueFamilyIndex, pPhysicalDevice->numOfQueueFamilies);
111211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
111311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pSupported) {
111411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSupported");
111511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
111611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
111711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
111811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
111911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.unlock();
112011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface,
112111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                      pSupported);
112211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.lock();
112311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
112411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Obtain this pointer again after locking:
112511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
112611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            auto it = my_data->physicalDeviceMap.find(physicalDevice);
112711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
112811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
112911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((result == VK_SUCCESS) && pSupported && pPhysicalDevice) {
113011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Record the result of this query:
113111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            SwpInstance *pInstance = pPhysicalDevice->pInstance;
113211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            SwpSurface *pSurface = (pInstance) ? pInstance->surfaces[surface] : NULL;
113311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (pSurface) {
113411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pPhysicalDevice->supportedSurfaces[surface] = pSurface;
113511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if (!pSurface->numQueueFamilyIndexSupport) {
113611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    if (pPhysicalDevice->gotQueueFamilyPropertyCount) {
113711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        pSurface->pQueueFamilyIndexSupport =
113811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            (VkBool32 *)malloc(pPhysicalDevice->numOfQueueFamilies * sizeof(VkBool32));
113911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        if (pSurface->pQueueFamilyIndexSupport != NULL) {
114011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            pSurface->numQueueFamilyIndexSupport = pPhysicalDevice->numOfQueueFamilies;
114111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        }
114211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    }
114311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
114411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if (pSurface->numQueueFamilyIndexSupport) {
114511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pSurface->pQueueFamilyIndexSupport[queueFamilyIndex] = *pSupported;
114611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
114711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
114811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
114911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
115011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
115111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return VK_ERROR_VALIDATION_FAILED_EXT;
115211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
115311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
115411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
115511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
115611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) {
115711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = VK_SUCCESS;
115811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
115911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
116011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
116111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpPhysicalDevice *pPhysicalDevice = NULL;
116211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
116311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->physicalDeviceMap.find(physicalDevice);
116411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
116511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
116611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
116711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the surface extension was enabled:
116811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
116911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
117011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
117111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
117211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_SURFACE_EXTENSION_NAME);
117311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
117411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pSurfaceCapabilities) {
117511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceCapabilities");
117611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
117711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
117811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
117911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
118011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.unlock();
118111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface,
118211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                           pSurfaceCapabilities);
118311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.lock();
118411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
118511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Obtain this pointer again after locking:
118611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
118711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            auto it = my_data->physicalDeviceMap.find(physicalDevice);
118811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
118911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
119011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((result == VK_SUCCESS) && pPhysicalDevice) {
119111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Record the result of this query:
119211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pPhysicalDevice->gotSurfaceCapabilities = true;
119311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // FIXME: NEED TO COPY THIS DATA, BECAUSE pSurfaceCapabilities POINTS TO APP-ALLOCATED DATA
119411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pPhysicalDevice->surfaceCapabilities = *pSurfaceCapabilities;
119511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
119611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
119711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
119811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return VK_ERROR_VALIDATION_FAILED_EXT;
119911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
120011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
120111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
120211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount,
120311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   VkSurfaceFormatKHR *pSurfaceFormats) {
120411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = VK_SUCCESS;
120511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
120611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
120711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
120811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpPhysicalDevice *pPhysicalDevice = NULL;
120911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
121011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->physicalDeviceMap.find(physicalDevice);
121111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
121211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
121311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
121411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the surface extension was enabled:
121511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
121611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
121711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
121811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
121911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_SURFACE_EXTENSION_NAME);
122011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
122111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pSurfaceFormatCount) {
122211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pSurfaceFormatCount");
122311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else if (pPhysicalDevice && pSurfaceFormats) {
122411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Compare the preliminary value of *pSurfaceFormatCount with the
122511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // value this time:
122611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pPhysicalDevice->surfaceFormatCount == 0) {
122711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Since we haven't recorded a preliminary value of
122811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // *pSurfaceFormatCount, that likely means that the application
122911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // didn't previously call this function with a NULL value of
123011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // pSurfaceFormats:
123111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
123211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
123311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                physicalDevice, "pSurfaceFormatCount", "pSurfaceFormats");
123411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        } else if (*pSurfaceFormatCount > pPhysicalDevice->surfaceFormatCount) {
123511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR_INVALID_COUNT(
123611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
123711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                physicalDevice, "pSurfaceFormatCount", "pSurfaceFormats",
123811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                *pSurfaceFormatCount, pPhysicalDevice->surfaceFormatCount);
123911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
124011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
124111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
124211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
124311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
124411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.unlock();
124511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount,
124611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                      pSurfaceFormats);
124711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.lock();
124811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
124911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Obtain this pointer again after locking:
125011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
125111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            auto it = my_data->physicalDeviceMap.find(physicalDevice);
125211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
125311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
125411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((result == VK_SUCCESS) && pPhysicalDevice && !pSurfaceFormats && pSurfaceFormatCount) {
125511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Record the result of this preliminary query:
125611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
125711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        } else if ((result == VK_SUCCESS) && pPhysicalDevice &&
125811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                   pSurfaceFormats && pSurfaceFormatCount &&
125911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                   (*pSurfaceFormatCount > 0)) {
126011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Record the result of this query:
126111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
126211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pPhysicalDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)malloc(*pSurfaceFormatCount * sizeof(VkSurfaceFormatKHR));
126311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (pPhysicalDevice->pSurfaceFormats) {
126411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                for (uint32_t i = 0; i < *pSurfaceFormatCount; i++) {
126511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pPhysicalDevice->pSurfaceFormats[i] = pSurfaceFormats[i];
126611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
126711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            } else {
126811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pPhysicalDevice->surfaceFormatCount = 0;
126911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
127011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
127111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
127211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
127311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return VK_ERROR_VALIDATION_FAILED_EXT;
127411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
127511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
127611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
127711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pPresentModeCount,
127811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        VkPresentModeKHR *pPresentModes) {
127911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = VK_SUCCESS;
128011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
128111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
128211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
128311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpPhysicalDevice *pPhysicalDevice = NULL;
128411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
128511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->physicalDeviceMap.find(physicalDevice);
128611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
128711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
128811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
128911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the surface extension was enabled:
129011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pPhysicalDevice && pPhysicalDevice->pInstance && !pPhysicalDevice->pInstance->surfaceExtensionEnabled) {
129111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, pPhysicalDevice->pInstance, "VkInstance",
129211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
129311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkInstance.", __FUNCTION__,
129411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_SURFACE_EXTENSION_NAME);
129511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
129611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pPresentModeCount) {
129711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, physicalDevice, "pPresentModeCount");
129811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else if (pPhysicalDevice && pPresentModes) {
129911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Compare the preliminary value of *pPresentModeCount with the
130011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // value this time:
130111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pPhysicalDevice->presentModeCount == 0) {
130211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Since we haven't recorded a preliminary value of
130311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // *pPresentModeCount, that likely means that the application
130411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // didn't previously call this function with a NULL value of
130511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // pPresentModes:
130611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
130711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
130811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                physicalDevice, "pPresentModeCount", "pPresentModes");
130911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        } else if (*pPresentModeCount > pPhysicalDevice->presentModeCount) {
131011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR_INVALID_COUNT(
131111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT,
131211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                physicalDevice, "pPresentModeCount", "pPresentModes",
131311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                *pPresentModeCount, pPhysicalDevice->presentModeCount);
131411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
131511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
131611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
131711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
131811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
131911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.unlock();
132011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->instance_dispatch_table->GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface,
132111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                           pPresentModeCount, pPresentModes);
132211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.lock();
132311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
132411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Obtain this pointer again after locking:
132511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
132611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            auto it = my_data->physicalDeviceMap.find(physicalDevice);
132711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
132811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
132911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((result == VK_SUCCESS) && pPhysicalDevice && !pPresentModes && pPresentModeCount) {
133011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Record the result of this preliminary query:
133111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pPhysicalDevice->presentModeCount = *pPresentModeCount;
133211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        } else if ((result == VK_SUCCESS) && pPhysicalDevice &&
133311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                   pPresentModes && pPresentModeCount &&
133411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                   (*pPresentModeCount > 0)) {
133511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Record the result of this query:
133611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pPhysicalDevice->presentModeCount = *pPresentModeCount;
133711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pPhysicalDevice->pPresentModes = (VkPresentModeKHR *)malloc(*pPresentModeCount * sizeof(VkPresentModeKHR));
133811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (pPhysicalDevice->pPresentModes) {
133911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                for (uint32_t i = 0; i < *pPresentModeCount; i++) {
134011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pPhysicalDevice->pPresentModes[i] = pPresentModes[i];
134111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
134211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            } else {
134311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pPhysicalDevice->presentModeCount = 0;
134411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
134511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
134611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
134711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
134811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return VK_ERROR_VALIDATION_FAILED_EXT;
134911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
135011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
135111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This function does the up-front validation work for vkCreateSwapchainKHR(),
135211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// and returns true if a logging callback indicates that the call down the
135311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// chain should be skipped:
135411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, VkSwapchainKHR *pSwapchain) {
135511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // TODO: Validate cases of re-creating a swapchain (the current code
135611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // assumes a new swapchain is being created).
135711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
135811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
135911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    char fn[] = "vkCreateSwapchainKHR";
136011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpDevice *pDevice = NULL;
136111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
136211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->deviceMap.find(device);
136311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
136411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
136511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
136611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the swapchain extension was enabled:
136711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pDevice && !pDevice->swapchainExtensionEnabled) {
136811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
136911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                         "%s() called even though the %s extension was not enabled for this VkDevice.", fn,
137011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                         VK_KHR_SWAPCHAIN_EXTENSION_NAME);
137111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
137211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pCreateInfo) {
137311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
137411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
137511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pCreateInfo->sType != VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR) {
137611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo",
137711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                              "VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR");
137811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
137911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pCreateInfo->pNext != NULL) {
138011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pCreateInfo");
138111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
138211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
138311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pSwapchain) {
138411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchain");
138511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
138611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
138711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Keep around a useful pointer to pPhysicalDevice:
138811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
138911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
139011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate pCreateInfo values with result of
139111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // vkGetPhysicalDeviceQueueFamilyProperties
139211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pPhysicalDevice && pPhysicalDevice->gotQueueFamilyPropertyCount) {
139311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; i++) {
139411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (pCreateInfo->pQueueFamilyIndices[i] >= pPhysicalDevice->numOfQueueFamilies) {
139511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                skipCall |= LOG_ERROR_QUEUE_FAMILY_INDEX_TOO_LARGE(VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, pPhysicalDevice,
139611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                   "VkPhysicalDevice", pCreateInfo->pQueueFamilyIndices[i],
139711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                   pPhysicalDevice->numOfQueueFamilies);
139811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
139911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
140011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
140111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
140211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate pCreateInfo values with the results of
140311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // vkGetPhysicalDeviceSurfaceCapabilitiesKHR():
140411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pPhysicalDevice || !pPhysicalDevice->gotSurfaceCapabilities) {
140511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
140611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called before calling "
140711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
140811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              fn);
140911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else if (pCreateInfo) {
141011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Validate pCreateInfo->surface to make sure that
141111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // vkGetPhysicalDeviceSurfaceSupportKHR() reported this as a supported
141211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // surface:
141311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        SwpSurface *pSurface = ((pPhysicalDevice) ? pPhysicalDevice->supportedSurfaces[pCreateInfo->surface] : NULL);
141411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!pSurface) {
141511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_UNSUPPORTED_SURFACE,
141611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  "%s() called with pCreateInfo->surface that "
141711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  "was not returned by "
141811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  "vkGetPhysicalDeviceSurfaceSupportKHR() "
141911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  "for the device.",
142011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  fn);
142111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
142211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
142311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Validate pCreateInfo->minImageCount against
142411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // VkSurfaceCapabilitiesKHR::{min|max}ImageCount:
142511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        VkSurfaceCapabilitiesKHR *pCapabilities = &pPhysicalDevice->surfaceCapabilities;
142611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((pCreateInfo->minImageCount < pCapabilities->minImageCount) ||
142711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            ((pCapabilities->maxImageCount > 0) && (pCreateInfo->minImageCount > pCapabilities->maxImageCount))) {
142811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
142911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  SWAPCHAIN_CREATE_SWAP_BAD_MIN_IMG_COUNT, "%s() called with pCreateInfo->minImageCount "
143011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                           "= %d, which is outside the bounds returned "
143111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                           "by vkGetPhysicalDeviceSurfaceCapabilitiesKHR() (i.e. "
143211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                           "minImageCount = %d, maxImageCount = %d).",
143311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  fn, pCreateInfo->minImageCount, pCapabilities->minImageCount, pCapabilities->maxImageCount);
143411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
143511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Validate pCreateInfo->imageExtent against
143611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // VkSurfaceCapabilitiesKHR::{current|min|max}ImageExtent:
143711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((pCapabilities->currentExtent.width == -1) &&
143811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            ((pCreateInfo->imageExtent.width < pCapabilities->minImageExtent.width) ||
143911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert             (pCreateInfo->imageExtent.width > pCapabilities->maxImageExtent.width) ||
144011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert             (pCreateInfo->imageExtent.height < pCapabilities->minImageExtent.height) ||
144111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert             (pCreateInfo->imageExtent.height > pCapabilities->maxImageExtent.height))) {
144211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR(
144311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_OUT_OF_BOUNDS_EXTENTS,
144411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                "%s() called with pCreateInfo->imageExtent = "
144511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                "(%d,%d), which is outside the bounds "
144611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                "returned by vkGetPhysicalDeviceSurfaceCapabilitiesKHR(): "
144711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                "currentExtent = (%d,%d), minImageExtent = "
144811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                "(%d,%d), maxImageExtent = (%d,%d).",
144911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height, pCapabilities->currentExtent.width,
145011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pCapabilities->currentExtent.height, pCapabilities->minImageExtent.width, pCapabilities->minImageExtent.height,
145111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pCapabilities->maxImageExtent.width, pCapabilities->maxImageExtent.height);
145211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
145311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((pCapabilities->currentExtent.width != -1) &&
145411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            ((pCreateInfo->imageExtent.width != pCapabilities->currentExtent.width) ||
145511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert             (pCreateInfo->imageExtent.height != pCapabilities->currentExtent.height))) {
145611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
145711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN, "%s() called with pCreateInfo->imageExtent = "
145811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                              "(%d,%d), which is not equal to the "
145911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                              "currentExtent = (%d,%d) returned by "
146011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                              "vkGetPhysicalDeviceSurfaceCapabilitiesKHR().",
146111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  fn, pCreateInfo->imageExtent.width, pCreateInfo->imageExtent.height,
146211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  pCapabilities->currentExtent.width, pCapabilities->currentExtent.height);
146311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
146411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Validate pCreateInfo->preTransform has one bit set (1st two
146511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // lines of if-statement), which bit is also set in
146611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // VkSurfaceCapabilitiesKHR::supportedTransforms (3rd line of if-statement):
146711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!pCreateInfo->preTransform || (pCreateInfo->preTransform & (pCreateInfo->preTransform - 1)) ||
146811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            !(pCreateInfo->preTransform & pCapabilities->supportedTransforms)) {
146911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // This is an error situation; one for which we'd like to give
147011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // the developer a helpful, multi-line error message.  Build it
147111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // up a little at a time, and then log it:
147211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            std::string errorString = "";
147311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            char str[1024];
147411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Here's the first part of the message:
147511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            sprintf(str, "%s() called with a non-supported "
147611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                         "pCreateInfo->preTransform (i.e. %s).  "
147711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                         "Supported values are:\n",
147811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    fn, surfaceTransformStr(pCreateInfo->preTransform));
147911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            errorString += str;
148011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            for (int i = 0; i < 32; i++) {
148111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // Build up the rest of the message:
148211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if ((1 << i) & pCapabilities->supportedTransforms) {
148311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    const char *newStr = surfaceTransformStr((VkSurfaceTransformFlagBitsKHR)(1 << i));
148411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    sprintf(str, "    %s\n", newStr);
148511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    errorString += str;
148611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
148711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
148811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Log the message that we've built up:
148911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
149011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM, LAYER_NAME,
149111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                "%s", errorString.c_str());
149211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
149311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Validate pCreateInfo->compositeAlpha has one bit set (1st two
149411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // lines of if-statement), which bit is also set in
149511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // VkSurfaceCapabilitiesKHR::supportedCompositeAlpha (3rd line of if-statement):
149611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!pCreateInfo->compositeAlpha || (pCreateInfo->compositeAlpha & (pCreateInfo->compositeAlpha - 1)) ||
149711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            !((pCreateInfo->compositeAlpha) & pCapabilities->supportedCompositeAlpha)) {
149811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // This is an error situation; one for which we'd like to give
149911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // the developer a helpful, multi-line error message.  Build it
150011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // up a little at a time, and then log it:
150111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            std::string errorString = "";
150211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            char str[1024];
150311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Here's the first part of the message:
150411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            sprintf(str, "%s() called with a non-supported "
150511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                         "pCreateInfo->compositeAlpha (i.e. %s).  "
150611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                         "Supported values are:\n",
150711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    fn, surfaceCompositeAlphaStr(pCreateInfo->compositeAlpha));
150811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            errorString += str;
150911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            for (int i = 0; i < 32; i++) {
151011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // Build up the rest of the message:
151111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if ((1 << i) & pCapabilities->supportedCompositeAlpha) {
151211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    const char *newStr = surfaceCompositeAlphaStr((VkCompositeAlphaFlagBitsKHR)(1 << i));
151311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    sprintf(str, "    %s\n", newStr);
151411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    errorString += str;
151511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
151611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
151711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Log the message that we've built up:
151811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
151911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA,
152011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                LAYER_NAME, "%s", errorString.c_str());
152111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
152211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Validate pCreateInfo->imageArraySize against
152311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // VkSurfaceCapabilitiesKHR::maxImageArraySize:
152411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > pCapabilities->maxImageArrayLayers)) {
152511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
152611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_SIZE, "%s() called with a non-supported "
152711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                            "pCreateInfo->imageArraySize (i.e. %d).  "
152811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                            "Minimum value is 1, maximum value is %d.",
152911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  fn, pCreateInfo->imageArrayLayers, pCapabilities->maxImageArrayLayers);
153011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
153111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Validate pCreateInfo->imageUsage against
153211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // VkSurfaceCapabilitiesKHR::supportedUsageFlags:
153311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pCreateInfo->imageUsage != (pCreateInfo->imageUsage & pCapabilities->supportedUsageFlags)) {
153411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
153511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS, "%s() called with a non-supported "
153611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                             "pCreateInfo->imageUsage (i.e. 0x%08x)."
153711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                             "  Supported flag bits are 0x%08x.",
153811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  fn, pCreateInfo->imageUsage, pCapabilities->supportedUsageFlags);
153911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
154011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
154111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
154211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate pCreateInfo values with the results of
154311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // vkGetPhysicalDeviceSurfaceFormatsKHR():
154411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pPhysicalDevice || !pPhysicalDevice->surfaceFormatCount) {
154511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
154611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called before calling "
154711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "vkGetPhysicalDeviceSurfaceFormatsKHR().",
154811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              fn);
154911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else if (pCreateInfo) {
155011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Validate pCreateInfo->imageFormat against
155111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // VkSurfaceFormatKHR::format:
155211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        bool foundFormat = false;
155311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        bool foundColorSpace = false;
155411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        bool foundMatch = false;
155511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for (uint32_t i = 0; i < pPhysicalDevice->surfaceFormatCount; i++) {
155611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (pCreateInfo->imageFormat == pPhysicalDevice->pSurfaceFormats[i].format) {
155711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // Validate pCreateInfo->imageColorSpace against
155811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // VkSurfaceFormatKHR::colorSpace:
155911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                foundFormat = true;
156011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
156111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    foundMatch = true;
156211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    break;
156311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
156411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            } else {
156511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if (pCreateInfo->imageColorSpace == pPhysicalDevice->pSurfaceFormats[i].colorSpace) {
156611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    foundColorSpace = true;
156711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
156811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
156911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
157011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!foundMatch) {
157111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (!foundFormat) {
157211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if (!foundColorSpace) {
157311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
157411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                          SWAPCHAIN_CREATE_SWAP_BAD_IMG_FMT_CLR_SP, "%s() called with neither a "
157511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                    "supported pCreateInfo->imageFormat "
157611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                    "(i.e. %d) nor a supported "
157711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                    "pCreateInfo->imageColorSpace "
157811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                    "(i.e. %d).",
157911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                          fn, pCreateInfo->imageFormat, pCreateInfo->imageColorSpace);
158011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                } else {
158111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
158211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                          SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT, "%s() called with a non-supported "
158311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                "pCreateInfo->imageFormat (i.e. %d).",
158411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                          fn, pCreateInfo->imageFormat);
158511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
158611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            } else if (!foundColorSpace) {
158711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
158811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                      SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE, "%s() called with a non-supported "
158911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                 "pCreateInfo->imageColorSpace (i.e. %d).",
159011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                      fn, pCreateInfo->imageColorSpace);
159111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
159211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
159311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
159411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
159511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate pCreateInfo values with the results of
159611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // vkGetPhysicalDeviceSurfacePresentModesKHR():
159711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pPhysicalDevice || !pPhysicalDevice->presentModeCount) {
159811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!pCreateInfo || (pCreateInfo->presentMode != VK_PRESENT_MODE_FIFO_KHR)) {
159911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_WITHOUT_QUERY,
160011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  "%s() called before calling "
160111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  "vkGetPhysicalDeviceSurfacePresentModesKHR().",
160211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  fn);
160311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
160411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else if (pCreateInfo) {
160511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Validate pCreateInfo->presentMode against
160611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // vkGetPhysicalDeviceSurfacePresentModesKHR():
160711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        bool foundMatch = false;
160811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for (uint32_t i = 0; i < pPhysicalDevice->presentModeCount; i++) {
160911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (pPhysicalDevice->pPresentModes[i] == pCreateInfo->presentMode) {
161011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                foundMatch = true;
161111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                break;
161211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
161311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
161411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!foundMatch) {
161511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
161611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  SWAPCHAIN_CREATE_SWAP_BAD_PRESENT_MODE, "%s() called with a non-supported "
161711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                          "pCreateInfo->presentMode (i.e. %s).",
161811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  fn, presentModeStr(pCreateInfo->presentMode));
161911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
162011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
162111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
162211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate pCreateInfo->imageSharingMode and related values:
162311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT) {
162411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((pCreateInfo->queueFamilyIndexCount <= 1) || !pCreateInfo->pQueueFamilyIndices) {
162511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
162611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  SWAPCHAIN_CREATE_SWAP_BAD_SHARING_VALUES, "%s() called with a supported "
162711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                            "pCreateInfo->sharingMode of (i.e. %s), "
162811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                            "but with a bad value(s) for "
162911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                            "pCreateInfo->queueFamilyIndexCount or "
163011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                            "pCreateInfo->pQueueFamilyIndices).",
163111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  fn, sharingModeStr(pCreateInfo->imageSharingMode));
163211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
163311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else if (pCreateInfo->imageSharingMode != VK_SHARING_MODE_EXCLUSIVE) {
163411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_CREATE_SWAP_BAD_SHARING_MODE,
163511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called with a non-supported "
163611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "pCreateInfo->imageSharingMode (i.e. %s).",
163711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              fn, sharingModeStr(pCreateInfo->imageSharingMode));
163811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
163911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
164011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate pCreateInfo->clipped:
164111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pCreateInfo && (pCreateInfo->clipped != VK_FALSE) && (pCreateInfo->clipped != VK_TRUE)) {
164211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_BAD_BOOL,
164311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called with a VkBool32 value that is "
164411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "neither VK_TRUE nor VK_FALSE, but has the "
164511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "numeric value of %d.",
164611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              fn, pCreateInfo->clipped);
164711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
164811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
164911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate pCreateInfo->oldSwapchain:
165011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pCreateInfo && pCreateInfo->oldSwapchain) {
165111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        SwpSwapchain *pOldSwapchain = NULL;
165211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
165311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          auto it = my_data->swapchainMap.find(pCreateInfo->oldSwapchain);
165411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          pOldSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
165511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
165611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pOldSwapchain) {
165711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (device != pOldSwapchain->pDevice->device) {
165811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
165911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                      SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE, "%s() called with a different VkDevice "
166011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                          "than the VkSwapchainKHR was created with.",
166111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                      __FUNCTION__);
166211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
166311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (pCreateInfo->surface != pOldSwapchain->pSurface->surface) {
166411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
166511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                      SWAPCHAIN_CREATE_SWAP_DIFF_SURFACE, "%s() called with pCreateInfo->oldSwapchain "
166611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                          "that has a different VkSurfaceKHR than "
166711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                          "pCreateInfo->surface.",
166811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                      fn);
166911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
167011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        } else {
167111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // TBD: Leave this in (not sure object_track will check this)?
167211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |=
167311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                LOG_ERROR_NON_VALID_OBJ(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pCreateInfo->oldSwapchain, "VkSwapchainKHR");
167411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
167511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
167611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
167711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return skipCall;
167811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
167911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
168011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo,
168111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                  const VkAllocationCallbacks *pAllocator,
168211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                  VkSwapchainKHR *pSwapchain) {
168311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = VK_SUCCESS;
168411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
168511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
168611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = validateCreateSwapchainKHR(device, pCreateInfo, pSwapchain);
168711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
168811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
168911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
169011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.unlock();
169111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->device_dispatch_table->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
169211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.lock();
169311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
169411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (result == VK_SUCCESS) {
169511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Remember the swapchain's handle, and link it to the device:
169611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            SwpDevice *pDevice = NULL;
169711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            {
169811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                auto it = my_data->deviceMap.find(device);
169911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
170011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
170111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
170211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->swapchainMap[*pSwapchain].swapchain = *pSwapchain;
170311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (pDevice) {
170411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pDevice->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
170511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
170611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->swapchainMap[*pSwapchain].pDevice = pDevice;
170711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->swapchainMap[*pSwapchain].imageCount = 0;
170811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->swapchainMap[*pSwapchain].usedAllocatorToCreate = (pAllocator != NULL);
170911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Store a pointer to the surface
171011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
171111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            SwpInstance *pInstance = (pPhysicalDevice) ? pPhysicalDevice->pInstance : NULL;
171211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            layer_data *my_instance_data =
171311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                ((pInstance) ? get_my_data_ptr(get_dispatch_key(pInstance->instance), layer_data_map) : NULL);
171411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            SwpSurface *pSurface = ((my_data && pCreateInfo) ? &my_instance_data->surfaceMap[pCreateInfo->surface] : NULL);
171511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->swapchainMap[*pSwapchain].pSurface = pSurface;
171611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (pSurface) {
171711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pSurface->swapchains[*pSwapchain] = &my_data->swapchainMap[*pSwapchain];
171811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
171911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
172011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
172111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
172211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return VK_ERROR_VALIDATION_FAILED_EXT;
172311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
172411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
172511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
172611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) {
172711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // TODOs:
172811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //
172911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // - Implement a check for validity language that reads: All uses of
173011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //   presentable images acquired from pname:swapchain must: have completed
173111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //   execution
173211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
173311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
173411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
173511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpDevice *pDevice = NULL;
173611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
173711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->deviceMap.find(device);
173811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
173911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
174011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
174111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the swapchain extension was enabled:
174211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pDevice && !pDevice->swapchainExtensionEnabled) {
174311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
174411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
174511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_SWAPCHAIN_EXTENSION_NAME);
174611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
174711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
174811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Regardless of skipCall value, do some internal cleanup:
174911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpSwapchain *pSwapchain = NULL;
175011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
175111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->swapchainMap.find(swapchain);
175211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
175311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
175411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pSwapchain) {
175511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Delete the SwpSwapchain associated with this swapchain:
175611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pSwapchain->pDevice) {
175711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pSwapchain->pDevice->swapchains.erase(swapchain);
175811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (device != pSwapchain->pDevice->device) {
175911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_DESTROY_SWAP_DIFF_DEVICE,
176011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                          "%s() called with a different VkDevice than the "
176111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                          "VkSwapchainKHR was created with.",
176211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                          __FUNCTION__);
176311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
176411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
176511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pSwapchain->pSurface) {
176611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pSwapchain->pSurface->swapchains.erase(swapchain);
176711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
176811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pSwapchain->imageCount) {
176911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pSwapchain->images.clear();
177011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
177111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((pAllocator != NULL) != pSwapchain->usedAllocatorToCreate) {
177211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, instance, "VkInstance", SWAPCHAIN_INCOMPATIBLE_ALLOCATOR,
177311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      "%s() called with incompatible pAllocator from when "
177411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      "the object was created.",
177511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      __FUNCTION__);
177611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
177711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        my_data->swapchainMap.erase(swapchain);
177811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
177911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    lock.unlock();
178011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
178111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
178211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
178311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        my_data->device_dispatch_table->DestroySwapchainKHR(device, swapchain, pAllocator);
178411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
178511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
178611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
178711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
178811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
178911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = VK_SUCCESS;
179011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
179111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
179211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
179311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpDevice *pDevice = NULL;
179411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
179511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->deviceMap.find(device);
179611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
179711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
179811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
179911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the swapchain extension was enabled:
180011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pDevice && !pDevice->swapchainExtensionEnabled) {
180111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
180211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
180311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_SWAPCHAIN_EXTENSION_NAME);
180411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
180511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpSwapchain *pSwapchain = NULL;
180611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
180711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->swapchainMap.find(swapchain);
180811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
180911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
181011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pSwapchainImageCount) {
181111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pSwapchainImageCount");
181211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else if (pSwapchain && pSwapchainImages) {
181311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Compare the preliminary value of *pSwapchainImageCount with the
181411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // value this time:
181511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pSwapchain->imageCount == 0) {
181611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Since we haven't recorded a preliminary value of
181711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // *pSwapchainImageCount, that likely means that the application
181811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // didn't previously call this function with a NULL value of
181911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // pSwapchainImages:
182011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR_ZERO_PRIOR_COUNT(
182111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
182211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                device, "pSwapchainImageCount", "pSwapchainImages");
182311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        } else if (*pSwapchainImageCount > pSwapchain->imageCount) {
182411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR_INVALID_COUNT(
182511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
182611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                device, "pSwapchainImageCount", "pSwapchainImages",
182711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                *pSwapchainImageCount, pSwapchain->imageCount);
182811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
182911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
183011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
183111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
183211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
183311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.unlock();
183411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->device_dispatch_table->GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
183511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.lock();
183611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
183711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Obtain this pointer again after locking:
183811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
183911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            auto it = my_data->swapchainMap.find(swapchain);
184011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
184111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
184211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((result == VK_SUCCESS) && pSwapchain && !pSwapchainImages && pSwapchainImageCount) {
184311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Record the result of this preliminary query:
184411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pSwapchain->imageCount = *pSwapchainImageCount;
184511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        } else if ((result == VK_SUCCESS) && pSwapchain && pSwapchainImages &&
184611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                   pSwapchainImageCount && (*pSwapchainImageCount > 0)) {
184711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Record the images and their state:
184811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pSwapchain->imageCount = *pSwapchainImageCount;
184911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            for (uint32_t i = 0; i < *pSwapchainImageCount; i++) {
185011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pSwapchain->images[i].image = pSwapchainImages[i];
185111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pSwapchain->images[i].pSwapchain = pSwapchain;
185211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pSwapchain->images[i].acquiredByApp = false;
185311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
185411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
185511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
185611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
185711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return VK_ERROR_VALIDATION_FAILED_EXT;
185811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
185911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
186011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
186111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                   VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex) {
186211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // TODOs:
186311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //
186411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // - Address the timeout.  Possibilities include looking at the state of the
186511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //   swapchain's images, depending on the timeout value.
186611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // - Implement a check for validity language that reads: If pname:semaphore is
186711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //   not sname:VK_NULL_HANDLE it must: be unsignalled
186811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // - Implement a check for validity language that reads: If pname:fence is not
186911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //   sname:VK_NULL_HANDLE it must: be unsignalled and mustnot: be associated
187011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //   with any other queue command that has not yet completed execution on that
187111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //   queue
187211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // - Record/update the state of the swapchain, in case an error occurs
187311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //   (e.g. VK_ERROR_OUT_OF_DATE_KHR).
187411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = VK_SUCCESS;
187511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
187611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
187711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
187811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpDevice *pDevice = NULL;
187911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
188011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->deviceMap.find(device);
188111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
188211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
188311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
188411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Validate that the swapchain extension was enabled:
188511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pDevice && !pDevice->swapchainExtensionEnabled) {
188611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
188711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
188811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VK_KHR_SWAPCHAIN_EXTENSION_NAME);
188911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
189011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if ((semaphore == VK_NULL_HANDLE) && (fence == VK_NULL_HANDLE)) {
189111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice", SWAPCHAIN_NO_SYNC_FOR_ACQUIRE,
189211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "%s() called with both the semaphore and fence parameters set to "
189311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              "VK_NULL_HANDLE (at least one should be used).", __FUNCTION__);
189411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
189511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpSwapchain *pSwapchain = NULL;
189611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
189711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        auto it = my_data->swapchainMap.find(swapchain);
189811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
189911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
190011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    SwpPhysicalDevice *pPhysicalDevice = pDevice->pPhysicalDevice;
190111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pSwapchain && pPhysicalDevice && pPhysicalDevice->gotSurfaceCapabilities) {
190211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Look to see if the application has already acquired the maximum
190311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // number of images, and this will push it past the spec-defined
190411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // limits:
190511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        uint32_t minImageCount = pPhysicalDevice->surfaceCapabilities.minImageCount;
190611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        uint32_t imagesAcquiredByApp = 0;
190711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for (uint32_t i = 0; i < pSwapchain->imageCount; i++) {
190811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (pSwapchain->images[i].acquiredByApp) {
190911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                imagesAcquiredByApp++;
191011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
191111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
191211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (imagesAcquiredByApp > (pSwapchain->imageCount - minImageCount)) {
191311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR(
191411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT,
191511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                swapchain, "VkSwapchainKHR",
191611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                SWAPCHAIN_APP_ACQUIRES_TOO_MANY_IMAGES,
191711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                "%s() called when it cannot succeed.  The application has "
191811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                "acquired %d image(s) that have not yet been presented.  The "
191911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                "maximum number of images that the application can "
192011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                "simultaneously acquire from this swapchain (including this "
192111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                "call to %s()) is %d.  That value is derived by subtracting "
192211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                "VkSurfaceCapabilitiesKHR::minImageCount (%d) from the number "
192311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                "of images in the swapchain (%d) and adding 1.\n",
192411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                __FUNCTION__, imagesAcquiredByApp, __FUNCTION__,
192511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                (pSwapchain->imageCount - minImageCount + 1),
192611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                minImageCount, pSwapchain->imageCount);
192711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
192811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
192911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pImageIndex) {
193011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pImageIndex");
193111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
193211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
193311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
193411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
193511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.unlock();
193611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->device_dispatch_table->AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
193711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.lock();
193811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
193911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Obtain this pointer again after locking:
194011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
194111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            auto it = my_data->swapchainMap.find(swapchain);
194211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
194311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
194411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR)) && pSwapchain) {
194511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Change the state of the image (now acquired by the application):
194611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pSwapchain->images[*pImageIndex].acquiredByApp = true;
194711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
194811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
194911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
195011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return VK_ERROR_VALIDATION_FAILED_EXT;
195111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
195211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
195311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo) {
195411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // TODOs:
195511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //
195611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // - Implement a check for validity language that reads: Any given element of
195711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //   sname:VkSemaphore in pname:pWaitSemaphores must: refer to a prior signal
195811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //   of that sname:VkSemaphore that won't be consumed by any other wait on that
195911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //   semaphore
196011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // - Record/update the state of the swapchain, in case an error occurs
196111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //   (e.g. VK_ERROR_OUT_OF_DATE_KHR).
196211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = VK_SUCCESS;
196311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
196411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
196511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
196611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!pPresentInfo) {
196711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
196811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
196911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pPresentInfo->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR) {
197011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR_WRONG_STYPE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo",
197111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                              "VK_STRUCTURE_TYPE_PRESENT_INFO_KHR");
197211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
197311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pPresentInfo->pNext != NULL) {
197411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_INFO_WRONG_NEXT(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo");
197511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
197611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!pPresentInfo->swapchainCount) {
197711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR_ZERO_VALUE(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->swapchainCount");
197811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
197911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!pPresentInfo->pSwapchains) {
198011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pSwapchains");
198111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
198211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!pPresentInfo->pImageIndices) {
198311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= LOG_ERROR_NULL_POINTER(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "pPresentInfo->pImageIndices");
198411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
198511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Note: pPresentInfo->pResults is allowed to be NULL
198611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
198711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
198811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::unique_lock<std::mutex> lock(global_lock);
198911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    for (uint32_t i = 0; pPresentInfo && (i < pPresentInfo->swapchainCount); i++) {
199011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        uint32_t index = pPresentInfo->pImageIndices[i];
199111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        SwpSwapchain *pSwapchain = NULL;
199211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
199311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
199411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
199511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
199611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pSwapchain) {
199711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (!pSwapchain->pDevice->swapchainExtensionEnabled) {
199811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, pSwapchain->pDevice, "VkDevice",
199911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                      SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED,
200011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                      "%s() called even though the %s extension was not enabled for this VkDevice.", __FUNCTION__,
200111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                      VK_KHR_SWAPCHAIN_EXTENSION_NAME);
200211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
200311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (index >= pSwapchain->imageCount) {
200411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
200511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                      SWAPCHAIN_INDEX_TOO_LARGE, "%s() called for an index that is too "
200611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                 "large (i.e. %d).  There are only %d "
200711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                 "images in this VkSwapchainKHR.\n",
200811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                      __FUNCTION__, index, pSwapchain->imageCount);
200911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            } else {
201011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if (!pSwapchain->images[index].acquiredByApp) {
201111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i],
201211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                          "VkSwapchainKHR", SWAPCHAIN_INDEX_NOT_IN_USE, "%s() returned an index (i.e. %d) "
201311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                        "for an image that is not acquired by "
201411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                        "the application.",
201511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                          __FUNCTION__, index);
201611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
201711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
201811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            SwpQueue *pQueue = NULL;
201911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            {
202011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                auto it = my_data->queueMap.find(queue);
202111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                pQueue = (it == my_data->queueMap.end()) ? NULL : &it->second;
202211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
202311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            SwpSurface *pSurface = pSwapchain->pSurface;
202411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (pQueue && pSurface && pSurface->numQueueFamilyIndexSupport) {
202511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                uint32_t queueFamilyIndex = pQueue->queueFamilyIndex;
202611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // Note: the 1st test is to ensure queueFamilyIndex is in range,
202711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // and the 2nd test is the validation check:
202811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if ((pSurface->numQueueFamilyIndexSupport > queueFamilyIndex) &&
202911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    (!pSurface->pQueueFamilyIndexSupport[queueFamilyIndex])) {
203011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    skipCall |=
203111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT, pPresentInfo->pSwapchains[i], "VkSwapchainKHR",
203211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, "%s() called with a swapchain whose "
203311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                              "surface is not supported for "
203411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                              "presention on this device with the "
203511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                              "queueFamilyIndex (i.e. %d) of the "
203611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                              "given queue.",
203711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  __FUNCTION__, queueFamilyIndex);
203811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
203911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
204011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
204111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
204211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
204311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
204411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
204511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.unlock();
204611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = my_data->device_dispatch_table->QueuePresentKHR(queue, pPresentInfo);
204711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        lock.lock();
204811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
204911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pPresentInfo && ((result == VK_SUCCESS) || (result == VK_SUBOPTIMAL_KHR))) {
205011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
205111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                int index = pPresentInfo->pImageIndices[i];
205211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                SwpSwapchain *pSwapchain = NULL;
205311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                {
205411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    auto it = my_data->swapchainMap.find(pPresentInfo->pSwapchains[i]);
205511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pSwapchain = (it == my_data->swapchainMap.end()) ? NULL : &it->second;
205611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
205711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if (pSwapchain) {
205811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    // Change the state of the image (no longer acquired by the
205911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    // application):
206011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    pSwapchain->images[index].acquiredByApp = false;
206111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
206211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
206311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
206411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
206511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
206611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return VK_ERROR_VALIDATION_FAILED_EXT;
206711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
206811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
206911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
207011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
207111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
207211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
207311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
207411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
207511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Call down the call chain:
207611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        my_data->device_dispatch_table->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
207711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
207811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Remember the queue's handle, and link it to the device:
207911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        std::lock_guard<std::mutex> lock(global_lock);
208011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        SwpDevice *pDevice = NULL;
208111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        {
208211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            auto it = my_data->deviceMap.find(device);
208311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pDevice = (it == my_data->deviceMap.end()) ? NULL : &it->second;
208411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
208511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        my_data->queueMap[&pQueue].queue = *pQueue;
208611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pDevice) {
208711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            pDevice->queues[*pQueue] = &my_data->queueMap[*pQueue];
208811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
208911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        my_data->queueMap[&pQueue].pDevice = pDevice;
209011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        my_data->queueMap[&pQueue].queueFamilyIndex = queueFamilyIndex;
209111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
209211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
209311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
209411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
209511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
209611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
209711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
209811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result =
209911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
210011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (VK_SUCCESS == result) {
210111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        std::lock_guard<std::mutex> lock(global_lock);
210211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback);
210311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
210411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return result;
210511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
210611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
210711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance,
210811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                         VkDebugReportCallbackEXT msgCallback,
210911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                         const VkAllocationCallbacks *pAllocator) {
211011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
211111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
211211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::lock_guard<std::mutex> lock(global_lock);
211311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
211411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
211511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
211611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
211711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
211811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
211911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
212011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix,
212111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                            pMsg);
212211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
212311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
212411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
212511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                  const char *pLayerName, uint32_t *pCount,
212611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                  VkExtensionProperties *pProperties) {
212711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
212811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return util_GetExtensionProperties(0, nullptr, pCount, pProperties);
212911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
213011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(physicalDevice);
213111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
213211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    dispatch_key key = get_dispatch_key(physicalDevice);
213311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(key, layer_data_map);
213411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return my_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
213511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
213611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
213711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction
213811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_core_instance_command(const char *name);
213911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
214011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction
214111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_khr_surface_command(const char *name, VkInstance instance);
214211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
214311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction
214411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_core_device_command(const char *name);
214511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
214611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction
214711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_khr_swapchain_command(const char *name, VkDevice dev);
214811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
214911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
215011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    PFN_vkVoidFunction proc = intercept_core_device_command(funcName);
215111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (proc)
215211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return proc;
215311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
215411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(device);
215511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
215611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data;
215711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
215811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
215911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkLayerDispatchTable *pDisp =  my_data->device_dispatch_table;
216011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
216111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    proc = intercept_khr_swapchain_command(funcName, device);
216211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (proc)
216311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return proc;
216411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
216511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pDisp->GetDeviceProcAddr == NULL)
216611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return NULL;
216711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return pDisp->GetDeviceProcAddr(device, funcName);
216811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
216911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
217011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
217111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    PFN_vkVoidFunction proc = intercept_core_instance_command(funcName);
217211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!proc)
217311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        proc = intercept_core_device_command(funcName);
217411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!proc)
217511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        proc = intercept_khr_swapchain_command(funcName, VK_NULL_HANDLE);
217611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (proc)
217711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return proc;
217811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
217911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(instance);
218011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
218111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data;
218211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
218311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
218411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
218511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    proc = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
218611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!proc)
218711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        proc = intercept_khr_surface_command(funcName, instance);
218811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (proc)
218911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return proc;
219011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
219111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pTable->GetInstanceProcAddr == NULL)
219211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return NULL;
219311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return pTable->GetInstanceProcAddr(instance, funcName);
219411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
219511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
219611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction
219711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_core_instance_command(const char *name) {
219811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static const struct {
219911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        const char *name;
220011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        PFN_vkVoidFunction proc;
220111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } core_instance_commands[] = {
220211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
220311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
220411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) },
220511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
220611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices) },
220711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
220811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties) },
220911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    };
221011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
221111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // we should never be queried for these commands
221211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(strcmp(name, "vkEnumerateInstanceLayerProperties") &&
221311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert           strcmp(name, "vkEnumerateInstanceExtensionProperties") &&
221411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert           strcmp(name, "vkEnumerateDeviceLayerProperties"));
221511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
221611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
221711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!strcmp(core_instance_commands[i].name, name))
221811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return core_instance_commands[i].proc;
221911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
222011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
222111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return nullptr;
222211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
222311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
222411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction
222511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_khr_surface_command(const char *name, VkInstance instance) {
222611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static const struct {
222711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        const char *name;
222811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        PFN_vkVoidFunction proc;
222911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } khr_surface_commands[] = {
223011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_ANDROID_KHR
223111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateAndroidSurfaceKHR) },
223211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_ANDROID_KHR
223311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_MIR_KHR
223411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkCreateMirSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateMirSurfaceKHR) },
223511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetPhysicalDeviceMirPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceMirPresentationSupportKHR) },
223611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_MIR_KHR
223711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_WAYLAND_KHR
223811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkCreateWaylandSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWaylandSurfaceKHR) },
223911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetPhysicalDeviceWaylandPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWaylandPresentationSupportKHR) },
224011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_WAYLAND_KHR
224111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_WIN32_KHR
224211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkCreateWin32SurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateWin32SurfaceKHR) },
224311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetPhysicalDeviceWin32PresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceWin32PresentationSupportKHR) },
224411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_WIN32_KHR
224511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_XCB_KHR
224611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkCreateXcbSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXcbSurfaceKHR) },
224711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetPhysicalDeviceXcbPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXcbPresentationSupportKHR) },
224811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_XCB_KHR
224911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef VK_USE_PLATFORM_XLIB_KHR
225011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkCreateXlibSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateXlibSurfaceKHR) },
225111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetPhysicalDeviceXlibPresentationSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceXlibPresentationSupportKHR) },
225211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // VK_USE_PLATFORM_XLIB_KHR
225311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySurfaceKHR) },
225411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetPhysicalDeviceSurfaceSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceSupportKHR) },
225511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetPhysicalDeviceSurfaceCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceCapabilitiesKHR) },
225611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetPhysicalDeviceSurfaceFormatsKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceFormatsKHR) },
225711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetPhysicalDeviceSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfacePresentModesKHR) },
225811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    };
225911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
226011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // do not check if VK_KHR_*_surface is enabled (why?)
226111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
226211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    for (size_t i = 0; i < ARRAY_SIZE(khr_surface_commands); i++) {
226311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!strcmp(khr_surface_commands[i].name, name))
226411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return khr_surface_commands[i].proc;
226511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
226611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
226711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return nullptr;
226811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
226911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
227011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction
227111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_core_device_command(const char *name) {
227211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static const struct {
227311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        const char *name;
227411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        PFN_vkVoidFunction proc;
227511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } core_device_commands[] = {
227611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
227711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice) },
227811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue) },
227911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    };
228011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
228111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) {
228211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!strcmp(core_device_commands[i].name, name))
228311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return core_device_commands[i].proc;
228411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
228511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
228611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return nullptr;
228711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
228811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
228911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction
229011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_khr_swapchain_command(const char *name, VkDevice dev) {
229111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static const struct {
229211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        const char *name;
229311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        PFN_vkVoidFunction proc;
229411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } khr_swapchain_commands[] = {
229511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR) },
229611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR) },
229711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR) },
229811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR) },
229911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR) },
230011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    };
230111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
230211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // do not check if VK_KHR_swapchain is enabled (why?)
230311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
230411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    for (size_t i = 0; i < ARRAY_SIZE(khr_swapchain_commands); i++) {
230511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!strcmp(khr_swapchain_commands[i].name, name))
230611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return khr_swapchain_commands[i].proc;
230711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
230811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
230911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return nullptr;
231011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
231111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
231211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} // namespace swapchain
231311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
231411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// vk_layer_logging.h expects these to be defined
231511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
231611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
231711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertvkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
231811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                               const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
231911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return swapchain::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
232011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
232111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
232211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance,
232311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                           VkDebugReportCallbackEXT msgCallback,
232411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                           const VkAllocationCallbacks *pAllocator) {
232511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    swapchain::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
232611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
232711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
232811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
232911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertvkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
233011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
233111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    swapchain::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
233211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
233311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
233411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// loader-layer interface v0
233511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
233611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
233711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertvkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
233811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return util_GetExtensionProperties(ARRAY_SIZE(swapchain::instance_extensions), swapchain::instance_extensions, pCount, pProperties);
233911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
234011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
234111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
234211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertvkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
234311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return util_GetLayerProperties(1, &swapchain::swapchain_layer, pCount, pProperties);
234411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
234511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
234611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
234711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertvkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
234811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return util_GetLayerProperties(1, &swapchain::swapchain_layer, pCount, pProperties);
234911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
235011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
235111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
235211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                    const char *pLayerName, uint32_t *pCount,
235311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                    VkExtensionProperties *pProperties) {
235411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // the layer command handles VK_NULL_HANDLE just fine
235511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return swapchain::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
235611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
235711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
235811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
235911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return swapchain::GetDeviceProcAddr(dev, funcName);
236011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
236111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
236211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
236311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
236411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceLayerProperties);
236511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties"))
236611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateDeviceLayerProperties);
236711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
236811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceExtensionProperties);
236911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!strcmp(funcName, "vkGetInstanceProcAddr"))
237011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return reinterpret_cast<PFN_vkVoidFunction>(vkGetInstanceProcAddr);
237111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
237211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return swapchain::GetInstanceProcAddr(instance, funcName);
237311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
2374