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: Mark Lobodzinski <mark@lunarg.com>
1911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Mike Stroyan     <mike@LunarG.com>
2011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Tobin Ehlis      <tobin@lunarg.com>
2111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */
2211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
2311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <stdio.h>
2411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <stdlib.h>
2511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <string.h>
2611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <unordered_map>
2711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <memory>
2811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
2911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_loader_platform.h"
3011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_dispatch_table_helper.h"
3111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if defined(__GNUC__)
3211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#pragma GCC diagnostic ignored "-Wwrite-strings"
3311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
3411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if defined(__GNUC__)
3511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#pragma GCC diagnostic warning "-Wwrite-strings"
3611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
3711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_struct_size_helper.h"
3811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "device_limits.h"
3911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vulkan/vk_layer.h"
4011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_layer_config.h"
4111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_enum_validate_helper.h"
4211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_layer_table.h"
4311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_layer_data.h"
4411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_layer_logging.h"
4511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_layer_extension_utils.h"
4611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_layer_utils.h"
4711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
4811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertnamespace device_limits {
4911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
5011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This struct will be stored in a map hashed by the dispatchable object
5111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct layer_data {
5211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkInstance instance;
5311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
5411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    debug_report_data *report_data;
5511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    std::vector<VkDebugReportCallbackEXT> logging_callback;
5611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkLayerDispatchTable *device_dispatch_table;
5711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkLayerInstanceDispatchTable *instance_dispatch_table;
5811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Track state of each instance
5911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    unique_ptr<INSTANCE_STATE> instanceState;
6011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    unique_ptr<PHYSICAL_DEVICE_STATE> physicalDeviceState;
6111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkPhysicalDeviceFeatures actualPhysicalDeviceFeatures;
6211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkPhysicalDeviceFeatures requestedPhysicalDeviceFeatures;
6311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
6411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Track physical device per logical device
6511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkPhysicalDevice physicalDevice;
6611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkPhysicalDeviceProperties physicalDeviceProperties;
6711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Vector indices correspond to queueFamilyIndex
6811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    vector<unique_ptr<VkQueueFamilyProperties>> queueFamilyProperties;
6911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
7011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data()
7111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        : report_data(nullptr), device_dispatch_table(nullptr), instance_dispatch_table(nullptr), instanceState(nullptr),
7211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert          physicalDeviceState(nullptr), actualPhysicalDeviceFeatures(), requestedPhysicalDeviceFeatures(), physicalDevice(){};
7311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
7411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
7511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic unordered_map<void *, layer_data *> layer_data_map;
7611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
7711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// TODO : This can be much smarter, using separate locks for separate global data
7811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic int globalLockInitialized = 0;
7911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic loader_platform_thread_mutex globalLock;
8011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic void init_device_limits(layer_data *my_data, const VkAllocationCallbacks *pAllocator) {
8211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_device_limits");
8411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!globalLockInitialized) {
8611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // TODO/TBD: Need to delete this mutex sometime.  How???  One
8711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // suggestion is to call this during vkCreateInstance(), and then we
8811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // can clean it up during vkDestroyInstance().  However, that requires
8911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // that the layer have per-instance locks.  We need to come back and
9011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // address this soon.
9111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        loader_platform_thread_create_mutex(&globalLock);
9211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        globalLockInitialized = 1;
9311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
9411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
9511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
9611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
9711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
9811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic const VkLayerProperties global_layer = {
9911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    "VK_LAYER_LUNARG_device_limits", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer",
10011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert};
10111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
10211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
10311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
10411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
10511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
10611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(chain_info->u.pLayerInfo);
10711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
10811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
10911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (fpCreateInstance == NULL) {
11011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return VK_ERROR_INITIALIZATION_FAILED;
11111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
11211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
11311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Advance the link info for the next element on the chain
11411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
11511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
11611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
11711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (result != VK_SUCCESS)
11811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
11911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
12011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
12111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instance = *pInstance;
12211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
12311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
12411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
12511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->report_data = debug_report_create_instance(my_data->instance_dispatch_table, *pInstance,
12611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                        pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
12711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
12811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    init_device_limits(my_data, pAllocator);
12911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instanceState = unique_ptr<INSTANCE_STATE>(new INSTANCE_STATE());
13011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
13111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return VK_SUCCESS;
13211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
13311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
13411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* hook DestroyInstance to remove tableInstanceMap entry */
13511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
13611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
13711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    dispatch_key key = get_dispatch_key(instance);
13811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(key, layer_data_map);
13911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
14011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    pTable->DestroyInstance(instance, pAllocator);
14111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
14211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Clean up logging callback, if any
14311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    while (my_data->logging_callback.size() > 0) {
14411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
14511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
14611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        my_data->logging_callback.pop_back();
14711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
14811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
14911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_debug_report_destroy_instance(my_data->report_data);
15011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    delete my_data->instance_dispatch_table;
15111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data_map.erase(key);
15211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (layer_data_map.empty()) {
15311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Release mutex when destroying last instance.
15411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        loader_platform_thread_delete_mutex(&globalLock);
15511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        globalLockInitialized = 0;
15611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
15711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
15811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
15911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
16011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) {
16111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
16211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
16311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (my_data->instanceState) {
16411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // For this instance, flag when vkEnumeratePhysicalDevices goes to QUERY_COUNT and then QUERY_DETAILS
16511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (NULL == pPhysicalDevices) {
16611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->instanceState->vkEnumeratePhysicalDevicesState = QUERY_COUNT;
16711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        } else {
16811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (UNCALLED == my_data->instanceState->vkEnumeratePhysicalDevicesState) {
16911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // Flag error here, shouldn't be calling this without having queried count
17011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                skipCall |=
17111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0,
17211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL",
17311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            "Invalid call sequence to vkEnumeratePhysicalDevices() w/ non-NULL pPhysicalDevices. You should first "
17411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            "call vkEnumeratePhysicalDevices() w/ NULL pPhysicalDevices to query pPhysicalDeviceCount.");
17511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            } // TODO : Could also flag a warning if re-calling this function in QUERY_DETAILS state
17611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            else if (my_data->instanceState->physicalDevicesCount != *pPhysicalDeviceCount) {
17711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // TODO: Having actual count match count from app is not a requirement, so this can be a warning
17811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
17911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL",
18011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    "Call to vkEnumeratePhysicalDevices() w/ pPhysicalDeviceCount value %u, but actual count "
18111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    "supported by this instance is %u.",
18211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    *pPhysicalDeviceCount, my_data->instanceState->physicalDevicesCount);
18311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
18411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->instanceState->vkEnumeratePhysicalDevicesState = QUERY_DETAILS;
18511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
18611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (skipCall)
18711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return VK_ERROR_VALIDATION_FAILED_EXT;
18811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        VkResult result =
18911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->instance_dispatch_table->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
19011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (NULL == pPhysicalDevices) {
19111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            my_data->instanceState->physicalDevicesCount = *pPhysicalDeviceCount;
19211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        } else { // Save physical devices
19311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
19411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(pPhysicalDevices[i]), layer_data_map);
19511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                phy_dev_data->physicalDeviceState = unique_ptr<PHYSICAL_DEVICE_STATE>(new PHYSICAL_DEVICE_STATE());
19611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // Init actual features for each physical device
19711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                my_data->instance_dispatch_table->GetPhysicalDeviceFeatures(pPhysicalDevices[i],
19811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                            &(phy_dev_data->actualPhysicalDeviceFeatures));
19911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
20011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
20111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
20211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
20311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, __LINE__,
20411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                DEVLIMITS_INVALID_INSTANCE, "DL", "Invalid instance (0x%" PRIxLEAST64 ") passed into vkEnumeratePhysicalDevices().",
20511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                (uint64_t)instance);
20611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
20711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return VK_ERROR_VALIDATION_FAILED_EXT;
20811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
20911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
21011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
21111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures *pFeatures) {
21211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
21311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    phy_dev_data->physicalDeviceState->vkGetPhysicalDeviceFeaturesState = QUERY_DETAILS;
21411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    phy_dev_data->instance_dispatch_table->GetPhysicalDeviceFeatures(physicalDevice, pFeatures);
21511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
21611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
21711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
21811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
21911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map)
22011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        ->instance_dispatch_table->GetPhysicalDeviceFormatProperties(physicalDevice, format, pFormatProperties);
22111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
22211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
22311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
22411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling,
22511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                       VkImageUsageFlags usage, VkImageCreateFlags flags,
22611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                       VkImageFormatProperties *pImageFormatProperties) {
22711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map)
22811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        ->instance_dispatch_table->GetPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, flags,
22911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                          pImageFormatProperties);
23011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
23111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
23211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
23311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) {
23411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
23511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    phy_dev_data->instance_dispatch_table->GetPhysicalDeviceProperties(physicalDevice, pProperties);
23611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
23711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
23811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
23911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
24011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                       VkQueueFamilyProperties *pQueueFamilyProperties) {
24111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
24211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
24311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (phy_dev_data->physicalDeviceState) {
24411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (NULL == pQueueFamilyProperties) {
24511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            phy_dev_data->physicalDeviceState->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_COUNT;
24611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        } else {
24711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Verify that for each physical device, this function is called first with NULL pQueueFamilyProperties ptr in order to
24811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // get count
24911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (UNCALLED == phy_dev_data->physicalDeviceState->vkGetPhysicalDeviceQueueFamilyPropertiesState) {
25011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
25111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL",
25211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    "Invalid call sequence to vkGetPhysicalDeviceQueueFamilyProperties() w/ non-NULL "
25311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    "pQueueFamilyProperties. You should first call vkGetPhysicalDeviceQueueFamilyProperties() w/ "
25411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    "NULL pQueueFamilyProperties to query pCount.");
25511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
25611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            // Then verify that pCount that is passed in on second call matches what was returned
25711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (phy_dev_data->physicalDeviceState->queueFamilyPropertiesCount != *pCount) {
25811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
25911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // TODO: this is not a requirement of the Valid Usage section for vkGetPhysicalDeviceQueueFamilyProperties, so
26011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                // provide as warning
26111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
26211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL",
26311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    "Call to vkGetPhysicalDeviceQueueFamilyProperties() w/ pCount value %u, but actual count "
26411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    "supported by this physicalDevice is %u.",
26511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                    *pCount, phy_dev_data->physicalDeviceState->queueFamilyPropertiesCount);
26611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
26711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            phy_dev_data->physicalDeviceState->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_DETAILS;
26811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
26911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (skipCall)
27011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return;
27111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        phy_dev_data->instance_dispatch_table->GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pCount,
27211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                      pQueueFamilyProperties);
27311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (NULL == pQueueFamilyProperties) {
27411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            phy_dev_data->physicalDeviceState->queueFamilyPropertiesCount = *pCount;
27511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        } else { // Save queue family properties
27611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            phy_dev_data->queueFamilyProperties.reserve(*pCount);
27711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            for (uint32_t i = 0; i < *pCount; i++) {
27811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                phy_dev_data->queueFamilyProperties.emplace_back(new VkQueueFamilyProperties(pQueueFamilyProperties[i]));
27911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
28011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
28111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return;
28211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
28311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0,
28411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                __LINE__, DEVLIMITS_INVALID_PHYSICAL_DEVICE, "DL",
28511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                "Invalid physicalDevice (0x%" PRIxLEAST64 ") passed into vkGetPhysicalDeviceQueueFamilyProperties().",
28611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                (uint64_t)physicalDevice);
28711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
28811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
28911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
29011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
29111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties *pMemoryProperties) {
29211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map)
29311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        ->instance_dispatch_table->GetPhysicalDeviceMemoryProperties(physicalDevice, pMemoryProperties);
29411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
29511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
29611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
29711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
29811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                             VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling,
29911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                             uint32_t *pNumProperties, VkSparseImageFormatProperties *pProperties) {
30011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map)
30111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        ->instance_dispatch_table->GetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage,
30211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                tiling, pNumProperties, pProperties);
30311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
30411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
30511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
30611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports) {
30711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
30811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    /* TODO: Verify viewportCount < maxViewports from VkPhysicalDeviceLimits */
30911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
31011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
31111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        my_data->device_dispatch_table->CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports);
31211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
31311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
31411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
31511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
31611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *pScissors) {
31711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
31811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    /* TODO: Verify scissorCount < maxViewports from VkPhysicalDeviceLimits */
31911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    /* TODO: viewportCount and scissorCount must match at draw time */
32011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
32111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
32211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        my_data->device_dispatch_table->CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors);
32311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
32411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
32511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
32611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Verify that features have been queried and verify that requested features are available
32711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic bool validate_features_request(layer_data *phy_dev_data) {
32811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
32911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Verify that all of the requested features are available
33011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Get ptrs into actual and requested structs and if requested is 1 but actual is 0, request is invalid
33111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkBool32 *actual = (VkBool32 *)&(phy_dev_data->actualPhysicalDeviceFeatures);
33211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkBool32 *requested = (VkBool32 *)&(phy_dev_data->requestedPhysicalDeviceFeatures);
33311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // TODO : This is a nice, compact way to loop through struct, but a bad way to report issues
33411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //  Need to provide the struct member name with the issue. To do that seems like we'll
33511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //  have to loop through each struct member which should be done w/ codegen to keep in synch.
33611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uint32_t errors = 0;
33711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uint32_t totalBools = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
33811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    for (uint32_t i = 0; i < totalBools; i++) {
33911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (requested[i] > actual[i]) {
34011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
34111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED,
34211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                "DL", "While calling vkCreateDevice(), requesting feature #%u in VkPhysicalDeviceFeatures struct, "
34311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                      "which is not available on this device.",
34411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                i);
34511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            errors++;
34611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
34711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
34811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (errors && (UNCALLED == phy_dev_data->physicalDeviceState->vkGetPhysicalDeviceFeaturesState)) {
34911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // If user didn't request features, notify them that they should
35011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // TODO: Verify this against the spec. I believe this is an invalid use of the API and should return an error
35111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
35211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED, "DL",
35311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            "You requested features that are unavailable on this device. You should first query feature "
35411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            "availability by calling vkGetPhysicalDeviceFeatures().");
35511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
35611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return skipCall;
35711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
35811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
35911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
36011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
36111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert             const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
36211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
36311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
36411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // First check is app has actually requested queueFamilyProperties
36511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!phy_dev_data->physicalDeviceState) {
36611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
36711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL",
36811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            "Invalid call to vkCreateDevice() w/o first calling vkEnumeratePhysicalDevices().");
36911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else if (QUERY_DETAILS != phy_dev_data->physicalDeviceState->vkGetPhysicalDeviceQueueFamilyPropertiesState) {
37011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // TODO: This is not called out as an invalid use in the spec so make more informative recommendation.
37111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
37211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST,
37311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            "DL", "Call to vkCreateDevice() w/o first calling vkGetPhysicalDeviceQueueFamilyProperties().");
37411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
37511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        // Check that the requested queue properties are valid
37611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
37711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            uint32_t requestedIndex = pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex;
37811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            if (phy_dev_data->queueFamilyProperties.size() <=
37911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                requestedIndex) { // requested index is out of bounds for this physical device
38011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                skipCall |= log_msg(
38111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0,
38211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, "DL",
38311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    "Invalid queue create request in vkCreateDevice(). Invalid queueFamilyIndex %u requested.", requestedIndex);
38411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            } else if (pCreateInfo->pQueueCreateInfos[i].queueCount >
38511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                       phy_dev_data->queueFamilyProperties[requestedIndex]->queueCount) {
38611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                skipCall |=
38711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
38811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST,
38911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            "DL", "Invalid queue create request in vkCreateDevice(). QueueFamilyIndex %u only has %u queues, but "
39011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                  "requested queueCount is %u.",
39111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            requestedIndex, phy_dev_data->queueFamilyProperties[requestedIndex]->queueCount,
39211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            pCreateInfo->pQueueCreateInfos[i].queueCount);
39311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
39411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
39511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
39611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Check that any requested features are available
39711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pCreateInfo->pEnabledFeatures) {
39811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        phy_dev_data->requestedPhysicalDeviceFeatures = *(pCreateInfo->pEnabledFeatures);
39911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= validate_features_request(phy_dev_data);
40011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
40111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (skipCall)
40211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return VK_ERROR_VALIDATION_FAILED_EXT;
40311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
40411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
40511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
40611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(chain_info->u.pLayerInfo);
40711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
40811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
40911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(phy_dev_data->instance, "vkCreateDevice");
41011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (fpCreateDevice == NULL) {
41111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return VK_ERROR_INITIALIZATION_FAILED;
41211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
41311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
41411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Advance the link info for the next element on the chain
41511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
41611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
41711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
41811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (result != VK_SUCCESS) {
41911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return result;
42011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
42111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
42211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
42311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_device_data->device_dispatch_table = new VkLayerDispatchTable;
42411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
42511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_device_data->report_data = layer_debug_report_create_device(phy_dev_data->report_data, *pDevice);
42611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_device_data->physicalDevice = gpu;
42711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
42811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Get physical device properties for this device
42911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    phy_dev_data->instance_dispatch_table->GetPhysicalDeviceProperties(gpu, &(my_device_data->physicalDeviceProperties));
43011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return result;
43111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
43211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
43311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
43411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
43511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // Free device lifetime allocations
43611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    dispatch_key key = get_dispatch_key(device);
43711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_device_data = get_my_data_ptr(key, layer_data_map);
43811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_device_data->device_dispatch_table->DestroyDevice(device, pAllocator);
43911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    delete my_device_data->device_dispatch_table;
44011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data_map.erase(key);
44111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
44211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
44311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
44411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
44511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                 const VkAllocationCallbacks *pAllocator,
44611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                 VkRenderPass *pRenderPass) {
44711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
44811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skip_call = false;
44911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    uint32_t max_color_attachments = dev_data->physicalDeviceProperties.limits.maxColorAttachments;
45011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
45111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pCreateInfo->pSubpasses[i].colorAttachmentCount > max_color_attachments) {
45211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
45311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                 reinterpret_cast<uint64_t>(device), __LINE__, DEVLIMITS_INVALID_ATTACHMENT_COUNT, "DL",
45411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                 "Cannot create a render pass with %d color attachments. Max is %d.",
45511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                 pCreateInfo->pSubpasses[i].colorAttachmentCount, max_color_attachments);
45611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
45711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
45811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (skip_call) {
45911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return VK_ERROR_VALIDATION_FAILED_EXT;
46011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
46111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return dev_data->device_dispatch_table->CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
46211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
46311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
46411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
46511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
46611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  const VkAllocationCallbacks *pAllocator,
46711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                  VkCommandPool *pCommandPool) {
46811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // TODO : Verify that requested QueueFamilyIndex for this pool exists
46911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = get_my_data_ptr(get_dispatch_key(device), layer_data_map)
47011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                          ->device_dispatch_table->CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool);
47111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return result;
47211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
47311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
47411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
47511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) {
47611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    get_my_data_ptr(get_dispatch_key(device), layer_data_map)
47711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        ->device_dispatch_table->DestroyCommandPool(device, commandPool, pAllocator);
47811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
47911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
48011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
48111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) {
48211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = get_my_data_ptr(get_dispatch_key(device), layer_data_map)
48311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                          ->device_dispatch_table->ResetCommandPool(device, commandPool, flags);
48411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return result;
48511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
48611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
48711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
48811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pCreateInfo, VkCommandBuffer *pCommandBuffer) {
48911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = get_my_data_ptr(get_dispatch_key(device), layer_data_map)
49011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                          ->device_dispatch_table->AllocateCommandBuffers(device, pCreateInfo, pCommandBuffer);
49111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return result;
49211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
49311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
49411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
49511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t count, const VkCommandBuffer *pCommandBuffers) {
49611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    get_my_data_ptr(get_dispatch_key(device), layer_data_map)
49711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        ->device_dispatch_table->FreeCommandBuffers(device, commandPool, count, pCommandBuffers);
49811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
49911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
50011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
50111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) {
50211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
50311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
50411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(dev_data->physicalDevice), layer_data_map);
50511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    const VkCommandBufferInheritanceInfo *pInfo = pBeginInfo->pInheritanceInfo;
50611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (phy_dev_data->actualPhysicalDeviceFeatures.inheritedQueries == VK_FALSE && pInfo && pInfo->occlusionQueryEnable != VK_FALSE) {
50711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= log_msg(
50811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
50911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            reinterpret_cast<uint64_t>(commandBuffer), __LINE__, DEVLIMITS_INVALID_INHERITED_QUERY, "DL",
51011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "Cannot set inherited occlusionQueryEnable in vkBeginCommandBuffer() when device does not support inheritedQueries.");
51111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
51211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (phy_dev_data->actualPhysicalDeviceFeatures.inheritedQueries != VK_FALSE && pInfo && pInfo->occlusionQueryEnable != VK_FALSE &&
51311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        !validate_VkQueryControlFlagBits(VkQueryControlFlagBits(pInfo->queryFlags))) {
51411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
51511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            reinterpret_cast<uint64_t>(commandBuffer), __LINE__, DEVLIMITS_INVALID_INHERITED_QUERY, "DL",
51611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            "Cannot enable in occlusion queries in vkBeginCommandBuffer() and set queryFlags to %d which is not a "
51711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            "valid combination of VkQueryControlFlagBits.",
51811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            pInfo->queryFlags);
51911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
52011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
52111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall)
52211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        result = dev_data->device_dispatch_table->BeginCommandBuffer(commandBuffer, pBeginInfo);
52311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return result;
52411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
52511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
52611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
52711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
52811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
52911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
53011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkPhysicalDevice gpu = dev_data->physicalDevice;
53111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
53211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (queueFamilyIndex >=
53311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        phy_dev_data->queueFamilyProperties.size()) { // requested index is out of bounds for this physical device
53411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
53511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST,
53611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                            "DL", "Invalid queueFamilyIndex %u requested in vkGetDeviceQueue().", queueFamilyIndex);
53711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else if (queueIndex >= phy_dev_data->queueFamilyProperties[queueFamilyIndex]->queueCount) {
53811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        skipCall |= log_msg(
53911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__,
54011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, "DL",
54111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            "Invalid queue request in vkGetDeviceQueue(). QueueFamilyIndex %u only has %u queues, but requested queueIndex is %u.",
54211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            queueFamilyIndex, phy_dev_data->queueFamilyProperties[queueFamilyIndex]->queueCount, queueIndex);
54311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
54411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall)
54511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        dev_data->device_dispatch_table->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
54611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
54711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
54811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
54911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites,
55011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                       uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies) {
55111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
55211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    bool skipCall = false;
55311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
55411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    for (uint32_t i = 0; i < descriptorWriteCount; i++) {
55511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if ((pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
55611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC)) {
55711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            VkDeviceSize uniformAlignment = dev_data->physicalDeviceProperties.limits.minUniformBufferOffsetAlignment;
55811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            for (uint32_t j = 0; j < pDescriptorWrites[i].descriptorCount; j++) {
55911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if (vk_safe_modulo(pDescriptorWrites[i].pBufferInfo[j].offset, uniformAlignment) != 0) {
56011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
56111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__,
56211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        DEVLIMITS_INVALID_UNIFORM_BUFFER_OFFSET, "DL",
56311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        "vkUpdateDescriptorSets(): pDescriptorWrites[%d].pBufferInfo[%d].offset (0x%" PRIxLEAST64
56411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        ") must be a multiple of device limit minUniformBufferOffsetAlignment 0x%" PRIxLEAST64,
56511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        i, j, pDescriptorWrites[i].pBufferInfo[j].offset, uniformAlignment);
56611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
56711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
56811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        } else if ((pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||
56911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                   (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
57011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            VkDeviceSize storageAlignment = dev_data->physicalDeviceProperties.limits.minStorageBufferOffsetAlignment;
57111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            for (uint32_t j = 0; j < pDescriptorWrites[i].descriptorCount; j++) {
57211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                if (vk_safe_modulo(pDescriptorWrites[i].pBufferInfo[j].offset, storageAlignment) != 0) {
57311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
57411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__,
57511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        DEVLIMITS_INVALID_STORAGE_BUFFER_OFFSET, "DL",
57611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        "vkUpdateDescriptorSets(): pDescriptorWrites[%d].pBufferInfo[%d].offset (0x%" PRIxLEAST64
57711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        ") must be a multiple of device limit minStorageBufferOffsetAlignment 0x%" PRIxLEAST64,
57811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                        i, j, pDescriptorWrites[i].pBufferInfo[j].offset, storageAlignment);
57911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                }
58011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            }
58111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
58211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
58311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!skipCall) {
58411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        dev_data->device_dispatch_table->UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
58511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                              pDescriptorCopies);
58611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
58711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
58811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
58911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
59011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer,
59111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint32_t *pData) {
59211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
59311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
59411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // dstOffset is the byte offset into the buffer to start updating and must be a multiple of 4.
59511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (dstOffset & 3) {
59611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
59711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
59811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    DEVLIMITS_INVALID_BUFFER_UPDATE_ALIGNMENT, "DL",
59911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    "vkCmdUpdateBuffer parameter, VkDeviceSize dstOffset, is not a multiple of 4")) {
60011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return;
60111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
60211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
60311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
60411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // dataSize is the number of bytes to update, which must be a multiple of 4.
60511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (dataSize & 3) {
60611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
60711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
60811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    DEVLIMITS_INVALID_BUFFER_UPDATE_ALIGNMENT, "DL",
60911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    "vkCmdUpdateBuffer parameter, VkDeviceSize dataSize, is not a multiple of 4")) {
61011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return;
61111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
61211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
61311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
61411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    dev_data->device_dispatch_table->CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
61511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
61611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
61711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
61811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) {
61911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
62011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
62111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // dstOffset is the byte offset into the buffer to start filling and must be a multiple of 4.
62211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (dstOffset & 3) {
62311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
62411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
62511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    DEVLIMITS_INVALID_BUFFER_UPDATE_ALIGNMENT, "DL",
62611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    "vkCmdFillBuffer parameter, VkDeviceSize dstOffset, is not a multiple of 4")) {
62711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return;
62811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
62911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
63011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
63111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // size is the number of bytes to fill, which must be a multiple of 4.
63211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (size & 3) {
63311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
63411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
63511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    DEVLIMITS_INVALID_BUFFER_UPDATE_ALIGNMENT, "DL",
63611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                    "vkCmdFillBuffer parameter, VkDeviceSize size, is not a multiple of 4")) {
63711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return;
63811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        }
63911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
64011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
64111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    dev_data->device_dispatch_table->CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data);
64211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
64311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
64411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
64511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
64611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                             const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
64711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
64811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkResult res = my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
64911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (VK_SUCCESS == res) {
65011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        res = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback);
65111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
65211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return res;
65311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
65411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
65511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
65611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDestroyDebugReportCallbackEXT(VkInstance instance,
65711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              VkDebugReportCallbackEXT msgCallback,
65811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                              const VkAllocationCallbacks *pAllocator) {
65911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
66011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
66111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
66211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
66311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
66411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
66511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
66611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                      size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
66711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
66811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix,
66911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                            pMsg);
67011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
67111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
67211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
67311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
67411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   const char *pLayerName, uint32_t *pCount,
67511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                   VkExtensionProperties *pProperties) {
67611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
67711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return util_GetExtensionProperties(0, nullptr, pCount, pProperties);
67811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
67911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(physicalDevice);
68011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
68111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    dispatch_key key = get_dispatch_key(physicalDevice);
68211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(key, layer_data_map);
68311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return my_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pCount, pProperties);
68411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
68511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
68611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction
68711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_core_instance_command(const char *name);
68811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
68911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction
69011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_core_device_command(const char *name);
69111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
69211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
69311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetDeviceProcAddr(VkDevice dev, const char *funcName) {
69411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    PFN_vkVoidFunction proc = intercept_core_device_command(funcName);
69511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (proc)
69611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return proc;
69711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
69811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(dev);
69911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
70011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data = get_my_data_ptr(get_dispatch_key(dev), layer_data_map);
70111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkLayerDispatchTable *pTable = my_data->device_dispatch_table;
70211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
70311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pTable->GetDeviceProcAddr == NULL)
70411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return NULL;
70511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return pTable->GetDeviceProcAddr(dev, funcName);
70611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
70711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
70811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
70911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
71011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertGetInstanceProcAddr(VkInstance instance, const char *funcName) {
71111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    PFN_vkVoidFunction proc = intercept_core_instance_command(funcName);
71211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!proc)
71311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        intercept_core_device_command(funcName);
71411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (proc)
71511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return proc;
71611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
71711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_data *my_data;
71811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
71911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(instance);
72011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
72111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
72211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    proc = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
72311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (proc)
72411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return proc;
72511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
72611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    {
72711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
72811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (pTable->GetInstanceProcAddr == NULL)
72911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return NULL;
73011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return pTable->GetInstanceProcAddr(instance, funcName);
73111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
73211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
73311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
73411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction
73511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_core_instance_command(const char *name) {
73611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static const struct {
73711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        const char *name;
73811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        PFN_vkVoidFunction proc;
73911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } core_instance_commands[] = {
74011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
74111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
74211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
74311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) },
74411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
74511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices) },
74611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetPhysicalDeviceFeatures", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceFeatures) },
74711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetPhysicalDeviceFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceFormatProperties) },
74811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetPhysicalDeviceImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceImageFormatProperties) },
74911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetPhysicalDeviceProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceProperties) },
75011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties) },
75111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetPhysicalDeviceMemoryProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceMemoryProperties) },
75211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetPhysicalDeviceSparseImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSparseImageFormatProperties) },
75311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
75411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    };
75511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
75611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // we should never be queried for these commands
75711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(strcmp(name, "vkEnumerateInstanceLayerProperties") &&
75811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert           strcmp(name, "vkEnumerateInstanceExtensionProperties") &&
75911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert           strcmp(name, "vkEnumerateDeviceLayerProperties"));
76011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
76111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
76211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!strcmp(core_instance_commands[i].name, name))
76311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return core_instance_commands[i].proc;
76411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
76511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
76611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return nullptr;
76711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
76811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
76911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic PFN_vkVoidFunction
77011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertintercept_core_device_command(const char *name) {
77111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    static const struct {
77211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        const char *name;
77311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        PFN_vkVoidFunction proc;
77411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } core_device_commands[] = {
77511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
77611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice) },
77711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue) },
77811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CreateRenderPass) },
77911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(CreateCommandPool) },
78011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyCommandPool) },
78111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkResetCommandPool", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandPool) },
78211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers) },
78311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(FreeCommandBuffers) },
78411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(BeginCommandBuffer) },
78511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkCmdUpdateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdUpdateBuffer) },
78611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSets) },
78711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkCmdFillBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdFillBuffer) },
78811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(CmdSetScissor) },
78911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        { "vkCmdSetViewport", reinterpret_cast<PFN_vkVoidFunction>(CmdSetViewport) },
79011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    };
79111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
79211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) {
79311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        if (!strcmp(core_device_commands[i].name, name))
79411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert            return core_device_commands[i].proc;
79511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
79611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
79711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return nullptr;
79811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
79911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
80011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} // namespace device_limits
80111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
80211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// vk_layer_logging.h expects these to be defined
80311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
80411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR VkResult VKAPI_CALL
80511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertvkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
80611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                               const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
80711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return device_limits::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
80811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
80911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
81011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
81111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertvkDestroyDebugReportCallbackEXT(VkInstance instance,
81211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                VkDebugReportCallbackEXT msgCallback,
81311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                const VkAllocationCallbacks *pAllocator) {
81411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    device_limits::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
81511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
81611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
81711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVKAPI_ATTR void VKAPI_CALL
81811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertvkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
81911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                        size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
82011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    device_limits::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
82111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
82211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
82311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// loader-layer interface v0
82411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
82511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
82611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertvkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
82711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return util_GetLayerProperties(1, &device_limits::global_layer, pCount, pProperties);
82811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
82911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
83011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
83111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertvkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
83211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return util_GetLayerProperties(1, &device_limits::global_layer, pCount, pProperties);
83311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
83411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
83511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
83611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertvkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
83711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return util_GetExtensionProperties(1, device_limits::instance_extensions, pCount, pProperties);
83811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
83911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
84011cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
84111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                    const char *pLayerName, uint32_t *pCount,
84211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                                                                                    VkExtensionProperties *pProperties) {
84311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    // the layer command handles VK_NULL_HANDLE just fine
84411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return device_limits::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
84511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
84611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
84711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
84811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return device_limits::GetDeviceProcAddr(dev, funcName);
84911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
85011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
85111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
85211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
85311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceLayerProperties);
85411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties"))
85511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateDeviceLayerProperties);
85611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
85711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceExtensionProperties);
85811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (!strcmp(funcName, "vkGetInstanceProcAddr"))
85911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return reinterpret_cast<PFN_vkVoidFunction>(vkGetInstanceProcAddr);
86011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
86111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return device_limits::GetInstanceProcAddr(instance, funcName);
86211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
863