/*
 * Copyright (c) 2021 The Khronos Group Inc.
 * Copyright (c) 2021 Valve Corporation
 * Copyright (c) 2021 LunarG, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and/or associated documentation files (the "Materials"), to
 * deal in the Materials without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Materials, and to permit persons to whom the Materials are
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice(s) and this permission notice shall be included in
 * all copies or substantial portions of the Materials.
 *
 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
 * USE OR OTHER DEALINGS IN THE MATERIALS.
 *
 * Author: Charles Giessen <charles@lunarg.com>
 */

#include "test_environment.h"
#include <functional>
#include <tuple>

enum class TestConfig {
    add_layer_implementation,
    add_layer_interception,
};

bool has_flag(std::vector<TestConfig> const& flags, TestConfig config) {
    for (auto const& flag : flags)
        if (flag == config) return true;
    return false;
}

/*
 Creates a TestICD with a function unknown to the loader called vkNotRealFuncTEST. The TestICD, when
 vk_icdGetPhysicalDeviceProcAddr is called, will return the custom_physical_device_function if the function name matches
 vkNotRealFuncTEST. The test then calls the function to verify that the unknown physical device function dispatching is
 working correctly.
*/
template <typename DispatchableHandleType>
struct custom_functions {
    static VKAPI_ATTR uint32_t VKAPI_CALL func_zero(DispatchableHandleType, uint32_t foo) { return foo; };
    static VKAPI_ATTR uint32_t VKAPI_CALL func_one(DispatchableHandleType, uint32_t foo, uint32_t bar) { return foo + bar; };
    static VKAPI_ATTR float VKAPI_CALL func_two(DispatchableHandleType, uint32_t foo, uint32_t bar, float baz) {
        return baz + foo + bar;
    };
    static VKAPI_ATTR int VKAPI_CALL func_three(DispatchableHandleType, int* ptr_a, int* ptr_b) { return *ptr_a + *ptr_b; };
    static VKAPI_ATTR float VKAPI_CALL func_four(DispatchableHandleType, int* ptr_a, int* ptr_b, int foo, int bar, float k, float l,
                                                 char a, char b, char c) {
        return *ptr_a + *ptr_b + foo + bar + k + l + static_cast<int>(a) + static_cast<int>(b) + static_cast<int>(c);
    };
};

/*
Functions for testing of layer interception of unknown functions. Note the need to pass a pointer to the layer and the name
of the called function as a parameter, this is necessary to allow a generic layer implementation, as the layer must look up
the function pointer to use. A real layer would store the function pointer in a dedicated structure per-instance/device, but
since the TestLayer is a generic layer, there isn't a fixed list of functions that should be supported.
*/

PFN_vkVoidFunction find_custom_func(TestLayer* layer, const char* name) {
    if (layer->custom_dispatch_functions.count(name) > 0) {
        return layer->custom_dispatch_functions.at(name);
    }
    return nullptr;
}

template <typename DispatchableHandleType>
struct layer_intercept_functions {
    static VKAPI_ATTR uint32_t VKAPI_CALL func_zero(DispatchableHandleType handle, TestLayer* layer, const char* name, uint32_t i) {
        auto func = reinterpret_cast<decltype(&func_zero)>(find_custom_func(layer, name));
        if (func == nullptr) return 1337;
        return func(handle, layer, name, i + 3);
    }
    static VKAPI_ATTR uint32_t VKAPI_CALL func_one(DispatchableHandleType handle, TestLayer* layer, const char* name, uint32_t i,
                                                   float f) {
        auto func = reinterpret_cast<decltype(&func_one)>(find_custom_func(layer, name));
        if (func == nullptr) return 1337;
        return func(handle, layer, name, i + 2, f + 1.f);
    }
    static VKAPI_ATTR float VKAPI_CALL func_two(DispatchableHandleType handle, TestLayer* layer, const char* name, uint32_t foo,
                                                uint32_t bar, float baz) {
        auto func = reinterpret_cast<decltype(&func_two)>(find_custom_func(layer, name));
        if (func == nullptr) return -1337;
        return func(handle, layer, name, foo + 1, bar + 2, baz * 2);
    };
    static VKAPI_ATTR int VKAPI_CALL func_three(DispatchableHandleType handle, TestLayer* layer, const char* name, int* ptr_a,
                                                int* ptr_b) {
        auto func = reinterpret_cast<decltype(&func_three)>(find_custom_func(layer, name));
        if (func == nullptr) return -1337;
        *ptr_a += 1;
        *ptr_b -= 2;
        return func(handle, layer, name, ptr_a, ptr_b);
    };
    static VKAPI_ATTR float VKAPI_CALL func_four(DispatchableHandleType handle, TestLayer* layer, const char* name, int* ptr_a,
                                                 int* ptr_b, int foo, int bar, float k, float l, char, char, char) {
        auto func = reinterpret_cast<decltype(&func_four)>(find_custom_func(layer, name));
        if (func == nullptr) return -1337.f;
        return func(handle, layer, name, ptr_a, ptr_b, foo + 4, bar + 5, k + 1, l + 2, 'd', 'e', 'f');
    };
};

template <typename DispatchableHandleType>
struct layer_implementation_functions {
    static VKAPI_ATTR uint32_t VKAPI_CALL func_zero(DispatchableHandleType, TestLayer*, const char*, uint32_t i) { return i * 3; }
    static VKAPI_ATTR uint32_t VKAPI_CALL func_one(DispatchableHandleType, TestLayer*, const char*, uint32_t i, float f) {
        return static_cast<int>(i * 3 + f * 10.f);
    }
    static VKAPI_ATTR float VKAPI_CALL func_two(DispatchableHandleType, TestLayer*, const char*, uint32_t foo, uint32_t bar,
                                                float baz) {
        return baz + foo + bar;
    };
    static VKAPI_ATTR int VKAPI_CALL func_three(DispatchableHandleType, TestLayer*, const char*, int* ptr_a, int* ptr_b) {
        return *ptr_a + *ptr_b;
    };
    static VKAPI_ATTR float VKAPI_CALL func_four(DispatchableHandleType, TestLayer*, const char*, int* ptr_a, int* ptr_b, int foo,
                                                 int bar, float k, float l, char a, char b, char c) {
        return *ptr_a + *ptr_b + foo + bar + k + l + static_cast<int>(a) + static_cast<int>(b) + static_cast<int>(c);
    };
};

// Add function_count strings to the func_names vector, starting at function_start place. Essentially a utility for filling
// up a list of names to use later
void add_function_names(std::vector<std::string>& func_names, uint32_t function_count, uint32_t function_start = 0) {
    for (uint32_t i = function_start; i < function_start + function_count;) {
        func_names.push_back(std::string("vkNotIntRealFuncTEST_") + std::to_string(i++));
        func_names.push_back(std::string("vkNotIntRealIntFuncTEST_") + std::to_string(i++));
        func_names.push_back(std::string("vkIntNotIntRealFloatFuncTEST_") + std::to_string(i++));
        func_names.push_back(std::string("vkNotRealFuncPointerPointerTEST_") + std::to_string(i++));
        func_names.push_back(std::string("vkNotRealFuncTEST_pointer_pointer_int_int_float_float_char_char_char_") +
                             std::to_string(i++));
    }
}

// Add data to the function_list, which could be a driver or a layer list of implementation functions.
template <typename FunctionStruct>
void fill_implementation_functions(std::vector<VulkanFunction>& function_list, std::vector<std::string>& func_names,
                                   FunctionStruct const& funcs, uint32_t function_count, uint32_t function_start = 0) {
    for (uint32_t i = function_start; i < function_start + function_count;) {
        function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_zero)});
        function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_one)});
        function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_two)});
        function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_three)});
        function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_four)});
    }
}

// Add device interception functions to a layer. Need to call `add_custom_device_interception_function` since the layer has
// to setup a unordered_map for storing the next function in the chain, and key it based on the name
template <typename FunctionStruct>
void fill_device_intercept_functions(TestLayer& layer, std::vector<std::string>& func_names, FunctionStruct const& funcs,
                                     uint32_t function_count, uint32_t function_start = 0) {
    for (uint32_t i = function_start; i < function_start + function_count;) {
        layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_zero));
        layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_one));
        layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_two));
        layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_three));
        layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_four));
    }
}
// Add physical device interception functions to a layer. Need to call `add_custom_device_interception_function` since the
// layer has to setup a unordered_map for storing the next function in the chain, and key it based on the name
template <typename FunctionStruct>
void fill_phys_dev_intercept_functions(TestLayer& layer, std::vector<std::string>& func_names, FunctionStruct const& funcs,
                                       uint32_t function_count, uint32_t function_start = 0) {
    for (uint32_t i = function_start; i < function_start + function_count;) {
        layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_zero));
        layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_one));
        layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_two));
        layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_three));
        layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_four));
    }
}

template <typename FunctionLoader, typename ParentType, typename DispatchableHandleType, typename FunctionStruct>
void check_custom_functions(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle, FunctionStruct const&,
                            std::vector<std::string>& func_names, uint32_t function_count, uint32_t function_start = 0) {
    for (uint32_t i = function_start; i < function_start + function_count;) {
        decltype(FunctionStruct::func_zero)* returned_func_i = loader.load(parent, func_names.at(i++).c_str());
        ASSERT_NE(returned_func_i, nullptr);
        EXPECT_EQ(returned_func_i(handle, i * 10), i * 10);

        decltype(FunctionStruct::func_one)* returned_func_ii = loader.load(parent, func_names.at(i++).c_str());
        ASSERT_NE(returned_func_ii, nullptr);
        EXPECT_EQ(returned_func_ii(handle, i * 10, i * 5), i * 10 + i * 5);

        decltype(FunctionStruct::func_two)* returned_func_iif = loader.load(parent, func_names.at(i++).c_str());
        ASSERT_NE(returned_func_iif, nullptr);
        EXPECT_NEAR(returned_func_iif(handle, i * 10, i * 5, 0.1234f), i * 10 + i * 5 + 0.1234f, 0.001);

        int x = 5;
        int y = -505;
        decltype(FunctionStruct::func_three)* returned_func_pp = loader.load(parent, func_names.at(i++).c_str());
        ASSERT_NE(returned_func_pp, nullptr);
        EXPECT_EQ(returned_func_pp(handle, &x, &y), -500);

        x = 5;
        y = -505;
        decltype(FunctionStruct::func_four)* returned_func_ppiiffccc = loader.load(parent, func_names.at(i++).c_str());
        ASSERT_NE(returned_func_ppiiffccc, nullptr);
        EXPECT_NEAR(returned_func_ppiiffccc(handle, &x, &y, 200, 300, 0.123f, 1001.89f, 'a', 'b', 'c'),
                    -500 + 200 + 300 + 0.123 + 1001.89 + 97 + 98 + 99, 0.001f);
    }
}

template <typename FunctionLoader, typename ParentType, typename DispatchableHandleType, typename FunctionStruct>
void check_layer_custom_functions(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle, TestLayer& layer,
                                  FunctionStruct const&, std::vector<std::string>& func_names, uint32_t function_count,
                                  uint32_t function_start = 0) {
    for (uint32_t i = function_start; i < function_start + function_count;) {
        decltype(FunctionStruct::func_zero)* returned_func_i = loader.load(parent, func_names.at(i).c_str());
        ASSERT_NE(returned_func_i, nullptr);
        EXPECT_EQ(returned_func_i(handle, &layer, func_names.at(i).c_str(), i), (i + 3) * 3);
        i++;
        decltype(FunctionStruct::func_one)* returned_func_if = loader.load(parent, func_names.at(i).c_str());
        ASSERT_NE(returned_func_if, nullptr);
        EXPECT_EQ(returned_func_if(handle, &layer, func_names.at(i).c_str(), i, i + 1.f), (i + 2) * 3 + (i + 2) * 10);
        i++;

        decltype(FunctionStruct::func_two)* returned_func_iif = loader.load(parent, func_names.at(i).c_str());
        ASSERT_NE(returned_func_iif, nullptr);
        EXPECT_NEAR(returned_func_iif(handle, &layer, func_names.at(i).c_str(), i * 10, i * 5, 0.1234f),
                    (i * 10 + 1) + (i * 5 + 2) + (0.1234f * 2.f), 0.001);
        i++;

        int x = 5 + i;
        int y = -505 - i;
        decltype(FunctionStruct::func_three)* returned_func_pp = loader.load(parent, func_names.at(i).c_str());
        ASSERT_NE(returned_func_pp, nullptr);
        EXPECT_EQ(returned_func_pp(handle, &layer, func_names.at(i).c_str(), &x, &y),
                  (5 + static_cast<int>(i) + 1) + (-505 - static_cast<int>(i) - 2));
        i++;

        x = 5;
        y = -505;
        decltype(FunctionStruct::func_four)* returned_func_ppiiffccc = loader.load(parent, func_names.at(i).c_str());
        ASSERT_NE(returned_func_ppiiffccc, nullptr);
        EXPECT_NEAR(
            returned_func_ppiiffccc(handle, &layer, func_names.at(i).c_str(), &x, &y, 200, 300, 0.123f, 1001.89f, 'a', 'b', 'c'),
            -500 + (200 + 4) + (300 + 5) + (0.123 + 1) + (1001.89 + 2) + 100 + 101 + 102,
            0.001f);  // layer changes abc to def
        i++;
    }
}

template <typename FunctionLoader, typename ParentType, typename DispatchableHandleType, typename FunctionStruct>
void check_layer_custom_functions_no_implementation(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle,
                                                    TestLayer& layer, FunctionStruct const&, std::vector<std::string>& func_names,
                                                    uint32_t function_count, uint32_t function_start = 0) {
    for (uint32_t i = function_start; i < function_start + function_count;) {
        decltype(FunctionStruct::func_zero)* returned_func_i = loader.load(parent, func_names.at(i).c_str());
        ASSERT_NE(returned_func_i, nullptr);
        EXPECT_EQ(1337U, returned_func_i(handle, &layer, func_names.at(i).c_str(), i));
        i++;
        decltype(FunctionStruct::func_one)* returned_func_if = loader.load(parent, func_names.at(i).c_str());
        ASSERT_NE(returned_func_if, nullptr);
        EXPECT_EQ(1337U, returned_func_if(handle, &layer, func_names.at(i).c_str(), i, i + 1.f));
        i++;

        decltype(FunctionStruct::func_two)* returned_func_iif = loader.load(parent, func_names.at(i).c_str());
        ASSERT_NE(returned_func_iif, nullptr);
        EXPECT_NEAR(-1337.0, returned_func_iif(handle, &layer, func_names.at(i).c_str(), i * 10, i * 5, 0.1234f), 0.001);
        i++;

        int x = 5 + i;
        int y = -505 - i;
        decltype(FunctionStruct::func_three)* returned_func_pp = loader.load(parent, func_names.at(i).c_str());
        ASSERT_NE(returned_func_pp, nullptr);
        EXPECT_EQ(-1337, returned_func_pp(handle, &layer, func_names.at(i).c_str(), &x, &y));
        i++;

        x = 5;
        y = -505;
        decltype(FunctionStruct::func_four)* returned_func_ppiiffccc = loader.load(parent, func_names.at(i).c_str());
        ASSERT_NE(returned_func_ppiiffccc, nullptr);
        EXPECT_NEAR(
            -1337.0,
            returned_func_ppiiffccc(handle, &layer, func_names.at(i).c_str(), &x, &y, 200, 300, 0.123f, 1001.89f, 'a', 'b', 'c'),
            0.001);
        i++;
    }
}

template <typename FunctionLoader, typename ParentType, typename DispatchableHandleType, typename FunctionStruct>
void check_layer_custom_functions_no_interception(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle,
                                                  TestLayer& layer, FunctionStruct const&, std::vector<std::string>& func_names,
                                                  uint32_t function_count, uint32_t function_start = 0) {
    for (uint32_t i = function_start; i < function_start + function_count;) {
        decltype(FunctionStruct::func_zero)* returned_func_i = loader.load(parent, func_names.at(i).c_str());
        ASSERT_NE(returned_func_i, nullptr);
        EXPECT_EQ(returned_func_i(handle, &layer, func_names.at(i).c_str(), i), (i)*3);
        i++;
        decltype(FunctionStruct::func_one)* returned_func_if = loader.load(parent, func_names.at(i).c_str());
        ASSERT_NE(returned_func_if, nullptr);
        EXPECT_EQ(returned_func_if(handle, &layer, func_names.at(i).c_str(), i, i + 1.f), (i)*3 + (i + 1) * 10);
        i++;

        decltype(FunctionStruct::func_two)* returned_func_iif = loader.load(parent, func_names.at(i).c_str());
        ASSERT_NE(returned_func_iif, nullptr);
        EXPECT_NEAR(returned_func_iif(handle, &layer, func_names.at(i).c_str(), i * 10, i * 5, 0.1234f),
                    (i * 10) + (i * 5) + (0.1234f), 0.001);
        i++;

        int x = 5 + i;
        int y = -505 - i;
        decltype(FunctionStruct::func_three)* returned_func_pp = loader.load(parent, func_names.at(i).c_str());
        ASSERT_NE(returned_func_pp, nullptr);
        EXPECT_EQ(returned_func_pp(handle, &layer, func_names.at(i).c_str(), &x, &y),
                  (5 + static_cast<int>(i)) + (-505 - static_cast<int>(i)));
        i++;

        x = 5;
        y = -505;
        decltype(FunctionStruct::func_four)* returned_func_ppiiffccc = loader.load(parent, func_names.at(i).c_str());
        ASSERT_NE(returned_func_ppiiffccc, nullptr);
        EXPECT_NEAR(
            returned_func_ppiiffccc(handle, &layer, func_names.at(i).c_str(), &x, &y, 200, 300, 0.123f, 1001.89f, 'a', 'b', 'c'),
            -500 + (200) + (300) + (0.123) + (1001.89) + 97 + 98 + 99, 0.001f);
        i++;
    }
}

using custom_physical_device_functions = custom_functions<VkPhysicalDevice>;
using layer_intercept_physical_device_functions = layer_intercept_functions<VkPhysicalDevice>;
using layer_implementation_physical_device_functions = layer_implementation_functions<VkPhysicalDevice>;

TEST(UnknownFunction, PhysicalDeviceFunction) {
    FrameworkEnvironment env{};
    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
    uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
    std::vector<std::string> function_names;
    add_function_names(function_names, function_count);

    fill_implementation_functions(driver.physical_devices.at(0).custom_physical_device_functions, function_names,
                                  custom_physical_device_functions{}, function_count);
    InstWrapper inst{env.vulkan_functions};
    inst.CheckCreate();

    VkPhysicalDevice phys_dev = inst.GetPhysDev();
    check_custom_functions(env.vulkan_functions, inst.inst, phys_dev, custom_physical_device_functions{}, function_names,
                           function_count);
}

TEST(UnknownFunction, PhysicalDeviceFunctionMultipleDriverSupport) {
    FrameworkEnvironment env{};
    auto& driver_0 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
    auto& driver_1 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
    uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
    std::vector<std::string> function_names;
    add_function_names(function_names, function_count);

    // used to identify the GPUs
    driver_0.physical_devices.emplace_back("physical_device_0").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
    driver_1.physical_devices.emplace_back("physical_device_1").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;

    for (uint32_t i = 0; i < function_count / 10; i++) {
        fill_implementation_functions(driver_0.physical_devices.at(0).custom_physical_device_functions, function_names,
                                      custom_physical_device_functions{}, 5, i * 10);
        fill_implementation_functions(driver_1.physical_devices.at(0).custom_physical_device_functions, function_names,
                                      custom_physical_device_functions{}, 5, i * 10 + 5);
    }
    InstWrapper inst{env.vulkan_functions};
    inst.CheckCreate();

    auto phys_devs = inst.GetPhysDevs(2);
    VkPhysicalDevice phys_dev_0 = phys_devs[0];
    VkPhysicalDevice phys_dev_1 = phys_devs[1];
    VkPhysicalDeviceProperties props{};
    env.vulkan_functions.vkGetPhysicalDeviceProperties(phys_devs[0], &props);
    if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
        phys_dev_0 = phys_devs[1];
        phys_dev_1 = phys_devs[0];
    }
    for (uint32_t i = 0; i < function_count / 10; i++) {
        check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_0, custom_physical_device_functions{}, function_names, 5,
                               i * 10);
        check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_1, custom_physical_device_functions{}, function_names, 5,
                               i * 10 + 5);
    }
}

// Add unknown functions to driver 0, and try to use them on driver 1.
TEST(UnknownFunctionDeathTests, PhysicalDeviceFunctionErrorPath) {
    FrameworkEnvironment env{};
    auto& driver_0 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
    auto& driver_1 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
    std::vector<std::string> function_names;
    add_function_names(function_names, 1);

    // used to identify the GPUs
    driver_0.physical_devices.emplace_back("physical_device_0").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
    driver_1.physical_devices.emplace_back("physical_device_1").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
    function_names.push_back(std::string("vkNotIntRealFuncTEST_0"));

    custom_physical_device_functions funcs{};
    driver_0.physical_devices.at(0).custom_physical_device_functions.push_back(
        VulkanFunction{function_names.back(), to_vkVoidFunction(funcs.func_zero)});

    InstWrapper inst{env.vulkan_functions};
    inst.CheckCreate();

    auto phys_devs = inst.GetPhysDevs(2);
    VkPhysicalDevice phys_dev_to_use = phys_devs[1];
    VkPhysicalDeviceProperties props{};
    env.vulkan_functions.vkGetPhysicalDeviceProperties(phys_devs[1], &props);
    if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) phys_dev_to_use = phys_devs[0];
    // use the wrong GPU to query the functions, should get 5 errors

    decltype(custom_physical_device_functions::func_zero)* returned_func_i =
        env.vulkan_functions.load(inst.inst, function_names.at(0).c_str());
    ASSERT_NE(returned_func_i, nullptr);
    ASSERT_DEATH(returned_func_i(phys_dev_to_use, 0), "Function vkNotIntRealFuncTEST_0 not supported for this physical device");
}

TEST(UnknownFunction, PhysicalDeviceFunctionWithImplicitLayerImplementation) {
    FrameworkEnvironment env{};
    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
    uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
    std::vector<std::string> function_names;
    add_function_names(function_names, function_count);

    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
                                                         .set_disable_environment("DISABLE_ME")),
                           "implicit_layer_unknown_function_intercept.json");
    auto& layer = env.get_test_layer();
    fill_implementation_functions(layer.custom_physical_device_implementation_functions, function_names,
                                  layer_implementation_physical_device_functions{}, function_count);

    InstWrapper inst{env.vulkan_functions};
    inst.CheckCreate();

    VkPhysicalDevice phys_dev = inst.GetPhysDev();
    check_layer_custom_functions_no_interception(env.vulkan_functions, inst.inst, phys_dev, layer,
                                                 layer_implementation_physical_device_functions{}, function_names, function_count);
}

TEST(UnknownFunction, PhysicalDeviceFunctionMultipleDriverSupportWithImplicitLayerImplementation) {
    FrameworkEnvironment env{};
    auto& driver_0 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
    auto& driver_1 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
    uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
    std::vector<std::string> function_names;
    add_function_names(function_names, function_count);

    // used to identify the GPUs
    driver_0.physical_devices.emplace_back("physical_device_0").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
    driver_1.physical_devices.emplace_back("physical_device_1").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
    for (uint32_t i = 0; i < function_count / 10; i++) {
        fill_implementation_functions(driver_0.physical_devices.at(0).custom_physical_device_functions, function_names,
                                      custom_physical_device_functions{}, 5, i * 10);
        fill_implementation_functions(driver_1.physical_devices.at(0).custom_physical_device_functions, function_names,
                                      custom_physical_device_functions{}, 5, i * 10 + 5);
    }

    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
                                                         .set_disable_environment("DISABLE_ME")),
                           "implicit_layer_unknown_function_intercept.json");

    InstWrapper inst{env.vulkan_functions};
    inst.CheckCreate();

    auto phys_devs = inst.GetPhysDevs(2);
    VkPhysicalDevice phys_dev_0 = phys_devs[0];
    VkPhysicalDevice phys_dev_1 = phys_devs[1];
    VkPhysicalDeviceProperties props{};
    env.vulkan_functions.vkGetPhysicalDeviceProperties(phys_devs[0], &props);
    if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
        phys_dev_0 = phys_devs[1];
        phys_dev_1 = phys_devs[0];
    }
    for (uint32_t i = 0; i < function_count / 10; i++) {
        check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_0, custom_physical_device_functions{}, function_names, 5,
                               i * 10);
        check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_1, custom_physical_device_functions{}, function_names, 5,
                               i * 10 + 5);
    }
}

TEST(UnknownFunction, PhysicalDeviceFunctionWithImplicitLayerInterception) {
    FrameworkEnvironment env{};
    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
    uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;

    std::vector<std::string> function_names;
    add_function_names(function_names, function_count);

    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
                                                         .set_disable_environment("DISABLE_ME")),
                           "implicit_layer_unknown_function_intercept.json");
    auto& layer = env.get_test_layer();
    fill_phys_dev_intercept_functions(layer, function_names, layer_intercept_physical_device_functions{}, function_count);

    InstWrapper inst{env.vulkan_functions};
    inst.CheckCreate();

    VkPhysicalDevice phys_dev = inst.GetPhysDev();
    check_layer_custom_functions_no_implementation(env.vulkan_functions, inst.inst, phys_dev, layer,
                                                   layer_intercept_physical_device_functions{}, function_names, function_count);
}

TEST(UnknownFunction, PhysicalDeviceFunctionDriverSupportWithImplicitLayerInterception) {
    FrameworkEnvironment env{};
    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
    uint32_t function_count = 100;
    std::vector<std::string> function_names;
    add_function_names(function_names, function_count);
    fill_implementation_functions(driver.physical_devices.at(0).custom_physical_device_functions, function_names,
                                  layer_implementation_physical_device_functions{}, function_count);
    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
                                                         .set_disable_environment("DISABLE_ME")),
                           "implicit_layer_unknown_function_intercept.json");
    auto& layer = env.get_test_layer();
    fill_phys_dev_intercept_functions(layer, function_names, layer_intercept_physical_device_functions{}, function_count);

    InstWrapper inst{env.vulkan_functions};
    inst.CheckCreate();

    VkPhysicalDevice phys_dev = inst.GetPhysDev();
    check_layer_custom_functions(env.vulkan_functions, inst.inst, phys_dev, layer, layer_intercept_physical_device_functions{},
                                 function_names, function_count);
}

TEST(UnknownFunction, PhysicalDeviceFunctionWithMultipleImplicitLayersInterception) {
    FrameworkEnvironment env{};
    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
    std::vector<std::string> function_names;
    uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
    add_function_names(function_names, function_count);
    driver.physical_devices.emplace_back("physical_device_0");

    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_0")
                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
                                                         .set_disable_environment("DISABLE_ME")),
                           "implicit_layer_unknown_function_intercept_0.json");
    auto& layer_0 = env.get_test_layer(0);
    layer_0.set_use_gipa_GetPhysicalDeviceProcAddr(true);
    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_1")
                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
                                                         .set_disable_environment("DISABLE_ME")),
                           "implicit_layer_unknown_function_intercept_1.json");
    auto& layer_1 = env.get_test_layer(1);
    layer_1.set_use_gipa_GetPhysicalDeviceProcAddr(false);
    for (uint32_t i = 0; i < function_count / 10; i++) {
        fill_implementation_functions(driver.physical_devices.at(0).custom_physical_device_functions, function_names,
                                      layer_implementation_physical_device_functions{}, 5, i * 10);
        fill_phys_dev_intercept_functions(layer_0, function_names, layer_intercept_physical_device_functions{}, 5, i * 10);
        fill_phys_dev_intercept_functions(layer_1, function_names, layer_intercept_physical_device_functions{}, 5, i * 10 + 5);
    }
    InstWrapper inst{env.vulkan_functions};
    inst.CheckCreate();

    VkPhysicalDevice phys_dev = inst.GetPhysDev();
    for (uint32_t i = 0; i < function_count / 10; i++) {
        check_layer_custom_functions(env.vulkan_functions, inst.inst, phys_dev, layer_0,
                                     layer_intercept_physical_device_functions{}, function_names, 5, i * 10);
        check_layer_custom_functions_no_implementation(env.vulkan_functions, inst.inst, phys_dev, layer_1,
                                                       layer_intercept_physical_device_functions{}, function_names, 5, i * 10 + 5);
    }
}

template <typename ParentType>
ParentType get_parent_type(InstWrapper const& inst, DeviceWrapper const& dev);

template <>
VkInstance get_parent_type<VkInstance>(InstWrapper const& inst, DeviceWrapper const&) {
    return inst.inst;
}
template <>
VkDevice get_parent_type<VkDevice>(InstWrapper const&, DeviceWrapper const& dev) {
    return dev.dev;
}

template <typename DispatchableHandleType>
DispatchableHandleType get_dispatch_handle(FrameworkEnvironment& env, DeviceWrapper const& dev,
                                           std::vector<TestConfig> const& flags);

template <>
VkDevice get_dispatch_handle<VkDevice>(FrameworkEnvironment&, DeviceWrapper const& dev, std::vector<TestConfig> const&) {
    return dev.dev;
}

template <>
VkCommandBuffer get_dispatch_handle<VkCommandBuffer>(FrameworkEnvironment& env, DeviceWrapper const& dev,
                                                     std::vector<TestConfig> const&) {
    VkCommandPool command_pool;
    VkCommandPoolCreateInfo pool_create_info{};
    DeviceFunctions funcs{env.vulkan_functions, dev};
    funcs.vkCreateCommandPool(dev, &pool_create_info, nullptr, &command_pool);
    VkCommandBuffer command_buffer;
    VkCommandBufferAllocateInfo alloc_info{};
    alloc_info.commandBufferCount = 1;
    alloc_info.commandPool = command_pool;
    funcs.vkAllocateCommandBuffers(dev, &alloc_info, &command_buffer);
    return command_buffer;
}

template <>
VkQueue get_dispatch_handle<VkQueue>(FrameworkEnvironment& env, DeviceWrapper const& dev, std::vector<TestConfig> const&) {
    DeviceFunctions funcs{env.vulkan_functions, dev.dev};
    VkQueue queue;
    funcs.vkGetDeviceQueue(dev, 0, 0, &queue);
    return queue;
}

template <typename ParentType, typename DispatchableHandleType>
void unknown_function_test_impl(std::vector<TestConfig> const& flags) {
    using custom_functions_type = custom_functions<DispatchableHandleType>;
    using layer_implementation_functions_type = layer_implementation_functions<DispatchableHandleType>;
    using layer_intercept_functions_type = layer_intercept_functions<DispatchableHandleType>;

    FrameworkEnvironment env{};
    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
    uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;

    std::vector<std::string> function_names;
    add_function_names(function_names, function_count);

    if (has_flag(flags, TestConfig::add_layer_interception)) {
        fill_implementation_functions(driver.physical_devices.back().known_device_functions, function_names,
                                      layer_implementation_functions_type{}, function_count);
    } else {
        fill_implementation_functions(driver.physical_devices.back().known_device_functions, function_names,
                                      custom_functions_type{}, function_count);
    }
    TestLayer* layer_ptr = nullptr;
    if (has_flag(flags, TestConfig::add_layer_implementation) || has_flag(flags, TestConfig::add_layer_interception)) {
        env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
                                                             .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
                                                             .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
                                                             .set_disable_environment("DISABLE_ME")),
                               "implicit_layer_unknown_function_intercept.json");
        layer_ptr = &env.get_test_layer();
    }
    if (has_flag(flags, TestConfig::add_layer_implementation) && has_flag(flags, TestConfig::add_layer_interception)) {
        for (uint32_t i = 0; i < function_count / 10; i++) {
            fill_implementation_functions(layer_ptr->custom_device_implementation_functions, function_names,
                                          layer_implementation_functions_type{}, 5, i * 10);
            fill_device_intercept_functions(*layer_ptr, function_names, layer_intercept_functions_type{}, 5, i * 10 + 5);
        }
    } else if (has_flag(flags, TestConfig::add_layer_implementation)) {
        fill_implementation_functions(layer_ptr->custom_device_implementation_functions, function_names, custom_functions_type{},
                                      function_count);
    } else if (has_flag(flags, TestConfig::add_layer_interception)) {
        fill_device_intercept_functions(*layer_ptr, function_names, layer_intercept_functions_type{}, function_count);
    }

    InstWrapper inst{env.vulkan_functions};
    inst.CheckCreate();

    DeviceWrapper dev{inst};
    dev.create_info.add_device_queue({});
    dev.CheckCreate(inst.GetPhysDev());
    auto dispatch_type = get_dispatch_handle<DispatchableHandleType>(env, dev, flags);
    auto parent_type = get_parent_type<ParentType>(inst, dev);

    if (has_flag(flags, TestConfig::add_layer_implementation) && has_flag(flags, TestConfig::add_layer_interception)) {
        for (uint32_t i = 0; i < function_count / 10; i++) {
            check_layer_custom_functions_no_interception(env.vulkan_functions, parent_type, dispatch_type, *layer_ptr,
                                                         layer_implementation_functions_type{}, function_names, 5, i * 10);
        }
    } else if (has_flag(flags, TestConfig::add_layer_interception)) {
        check_layer_custom_functions(env.vulkan_functions, parent_type, dispatch_type, *layer_ptr, layer_intercept_functions_type{},
                                     function_names, function_count);

    } else {
        check_custom_functions(env.vulkan_functions, parent_type, dispatch_type, custom_functions_type{}, function_names,
                               function_count);
    }
}

// Device

TEST(UnknownFunction, DeviceFromGDPA) { unknown_function_test_impl<VkDevice, VkDevice>({}); }

TEST(UnknownFunction, DeviceFromGDPAWithLayerImplementation) {
    unknown_function_test_impl<VkDevice, VkDevice>({TestConfig::add_layer_implementation});
}

TEST(UnknownFunction, DeviceFromGDPAWithLayerInterception) {
    unknown_function_test_impl<VkDevice, VkDevice>({TestConfig::add_layer_interception});
}

TEST(UnknownFunction, DeviceFromGDPAWithLayerInterceptionAndLayerImplementation) {
    unknown_function_test_impl<VkDevice, VkDevice>({TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
}

TEST(UnknownFunction, DeviceFromGIPA) { unknown_function_test_impl<VkInstance, VkDevice>({}); }

TEST(UnknownFunction, DeviceFromGIPAWithLayerImplementation) {
    unknown_function_test_impl<VkInstance, VkDevice>({TestConfig::add_layer_implementation});
}

TEST(UnknownFunction, DeviceFromGIPAWithLayerInterception) {
    unknown_function_test_impl<VkInstance, VkDevice>({TestConfig::add_layer_implementation});
}

TEST(UnknownFunction, DeviceFromGIPAWithLayerInterceptionAndLayerImplementation) {
    unknown_function_test_impl<VkInstance, VkDevice>({TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
}

// Command buffers

TEST(UnknownFunction, CommandBufferFromGDPA) { unknown_function_test_impl<VkDevice, VkCommandBuffer>({}); }

TEST(UnknownFunction, CommandBufferFromGDPAWithLayerImplementation) {
    unknown_function_test_impl<VkDevice, VkCommandBuffer>({TestConfig::add_layer_implementation});
}

TEST(UnknownFunction, CommandBufferFromGDPAWithLayerInterception) {
    unknown_function_test_impl<VkDevice, VkCommandBuffer>({TestConfig::add_layer_interception});
}

TEST(UnknownFunction, CommandBufferFromGDPAWithLayerInterceptionAndLayerImplementation) {
    unknown_function_test_impl<VkDevice, VkCommandBuffer>(
        {TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
}

TEST(UnknownFunction, CommandBufferFromGIPA) { unknown_function_test_impl<VkInstance, VkCommandBuffer>({}); }

TEST(UnknownFunction, CommandBufferFromGIPAWithLayerImplementation) {
    unknown_function_test_impl<VkInstance, VkCommandBuffer>({TestConfig::add_layer_implementation});
}

TEST(UnknownFunction, CommandBufferFromGIPAWithLayerInterception) {
    unknown_function_test_impl<VkInstance, VkCommandBuffer>({TestConfig::add_layer_implementation});
}

TEST(UnknownFunction, CommandBufferFromGIPAWithLayerInterceptionAndLayerImplementation) {
    unknown_function_test_impl<VkInstance, VkCommandBuffer>(
        {TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
}

// Queues

TEST(UnknownFunction, QueueFromGDPA) { unknown_function_test_impl<VkDevice, VkQueue>({}); }

TEST(UnknownFunction, QueueFromGDPAWithLayerImplementation) {
    unknown_function_test_impl<VkDevice, VkQueue>({TestConfig::add_layer_implementation});
}

TEST(UnknownFunction, QueueFromGDPAWithLayerInterception) {
    unknown_function_test_impl<VkDevice, VkQueue>({TestConfig::add_layer_interception});
}

TEST(UnknownFunction, QueueFromGDPAWithLayerInterceptionAndLayerImplementation) {
    unknown_function_test_impl<VkDevice, VkQueue>({TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
}

TEST(UnknownFunction, QueueFromGIPA) { unknown_function_test_impl<VkInstance, VkQueue>({}); }

TEST(UnknownFunction, QueueFromGIPAWithLayer) {
    unknown_function_test_impl<VkInstance, VkQueue>({TestConfig::add_layer_implementation});
}

TEST(UnknownFunction, QueueFromGIPAWithLayerInterception) {
    unknown_function_test_impl<VkInstance, VkQueue>({TestConfig::add_layer_implementation});
}

TEST(UnknownFunction, QueueFromGIPAWithLayerInterceptionAndLayerImplementation) {
    unknown_function_test_impl<VkInstance, VkQueue>({TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
}

/*
 The purpose of LayerInterceptData is to provide a place to store data that is accessible inside the interception function.
 It works by being a templated type with static variables. Every unique type used creates a new template instantiation, with its own
 static variable storage. Thus interception functions that are templated correctly have per-template static data storage at their
 disposal, which is used to query the next function in the chain and call down.
*/

template <typename UniqueType>
struct LayerInterceptData {
    static TestLayer* layer;
    static const char* name;
};
template <typename UniqueType>
TestLayer* LayerInterceptData<UniqueType>::layer = nullptr;
template <typename UniqueType>
const char* LayerInterceptData<UniqueType>::name = nullptr;

template <typename DispatchableHandle>
struct FunctionZero {
    static VKAPI_ATTR uint32_t VKAPI_CALL implementation(DispatchableHandle, uint32_t a, uint32_t b) { return a + b; }

    template <typename LayerType>
    static VKAPI_ATTR uint32_t VKAPI_CALL intercept(DispatchableHandle handle, uint32_t a, uint32_t b) {
        decltype(implementation)* func =
            reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
        if (func == nullptr) return 1337;
        return func(handle, a + 3, b + 7);
    }

    template <typename ParentType>
    static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
                      uint32_t interception_count = 1) {
        decltype(implementation)* returned_func = loader.load(parent, name);
        ASSERT_NE(returned_func, nullptr);
        EXPECT_EQ(returned_func(dispatch_type, 4, 9), (4 + 3 * interception_count) + (9 + 7 * interception_count));
    }
    template <typename ParentType>
    static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
                                        const char* name) {
        decltype(implementation)* returned_func = loader.load(parent, name);
        ASSERT_NE(returned_func, nullptr);
        EXPECT_EQ(returned_func(dispatch_type, 5, 2), 1337U);
    }
};

template <typename DispatchableHandle>
struct FunctionOne {
    static VKAPI_ATTR uint32_t VKAPI_CALL implementation(DispatchableHandle, uint32_t a, uint32_t b, char c) { return a + b + c; }

    template <typename LayerType>
    static VKAPI_ATTR uint32_t VKAPI_CALL intercept(DispatchableHandle handle, uint32_t a, uint32_t b, char c) {
        decltype(implementation)* func =
            reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
        if (func == nullptr) return 1337;
        return func(handle, a + 2, b + 9, c + 1);
    }

    template <typename ParentType>
    static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
                      uint32_t interception_count = 1) {
        decltype(implementation)* returned_func = loader.load(parent, name);
        ASSERT_NE(returned_func, nullptr);
        EXPECT_EQ(returned_func(dispatch_type, 12, 17, 'a'),
                  (12 + 2 * interception_count) + (17 + 9 * interception_count) + ('a' + 1 * interception_count));
    }
    template <typename ParentType>
    static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
                                        const char* name) {
        decltype(implementation)* returned_func = loader.load(parent, name);
        ASSERT_NE(returned_func, nullptr);
        EXPECT_EQ(returned_func(dispatch_type, 1, 516, 'c'), 1337U);
    }
};

template <typename DispatchableHandle>
struct FunctionTwo {
    static VKAPI_ATTR float VKAPI_CALL implementation(DispatchableHandle, int* ptr_a, int* ptr_b) {
        return 0.123f + *ptr_a + *ptr_b;
    }

    template <typename LayerType>
    static VKAPI_ATTR float VKAPI_CALL intercept(DispatchableHandle handle, int* ptr_a, int* ptr_b) {
        decltype(implementation)* func =
            reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
        if (func == nullptr) return -1337.f;
        *ptr_a += 2;
        *ptr_b += 5;
        return func(handle, ptr_a, ptr_b);
    }

    template <typename ParentType>
    static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
                      uint32_t interception_count = 1) {
        decltype(implementation)* returned_func = loader.load(parent, name);
        ASSERT_NE(returned_func, nullptr);
        int x = 10, y = 3;
        EXPECT_NEAR(returned_func(dispatch_type, &x, &y), 0.123f + (10 + 2 * interception_count) + (3 + 5 * interception_count),
                    0.001);
    }
    template <typename ParentType>
    static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
                                        const char* name) {
        decltype(implementation)* returned_func = loader.load(parent, name);
        ASSERT_NE(returned_func, nullptr);
        int x = 10, y = 0;
        EXPECT_NEAR(returned_func(dispatch_type, &x, &y), -1337.f, 0.001);
    }
};

template <typename DispatchableHandle>
struct FunctionThree {
    static VKAPI_ATTR float VKAPI_CALL implementation(DispatchableHandle, int* ptr_a, float* ptr_b, uint32_t c) {
        return 0.456f + *ptr_a + *ptr_b + c;
    }

    template <typename LayerType>
    static VKAPI_ATTR float VKAPI_CALL intercept(DispatchableHandle handle, int* ptr_a, float* ptr_b, uint32_t c) {
        decltype(implementation)* func =
            reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
        if (func == nullptr) return -1837.f;
        *ptr_a += 55;
        *ptr_b += 5.98f;
        return func(handle, ptr_a, ptr_b, c + 100);
    }

    template <typename ParentType>
    static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
                      uint32_t interception_count = 1) {
        decltype(implementation)* returned_func = loader.load(parent, name);
        ASSERT_NE(returned_func, nullptr);
        int x = 96;
        float y = 7;
        EXPECT_NEAR(returned_func(dispatch_type, &x, &y, 30),
                    0.456f + (96 + 55 * interception_count) + (7 + 5.98f * interception_count) + (30 + 100 * interception_count),
                    0.001);
    }
    template <typename ParentType>
    static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
                                        const char* name) {
        decltype(implementation)* returned_func = loader.load(parent, name);
        ASSERT_NE(returned_func, nullptr);
        int x = 10;
        float y = 0;
        EXPECT_NEAR(returned_func(dispatch_type, &x, &y, 40), -1837.f, 0.001);
    }
};

template <typename DispatchableHandle>
struct FunctionFour {
    static VKAPI_ATTR VkResult VKAPI_CALL implementation(DispatchableHandle, VkPhysicalDeviceLimits* limits, uint32_t* count,
                                                         VkExtensionProperties* props) {
        limits->nonCoherentAtomSize = 0x0000ABCD0000FEDCU;
        if (props == nullptr) {
            *count = 5;
            return VK_INCOMPLETE;
        } else {
            for (uint32_t i = 0; i < *count; i++) {
                props[i].specVersion = i;
            }
            return VK_SUCCESS;
        }
    }

    template <typename LayerType>
    static VKAPI_ATTR VkResult VKAPI_CALL intercept(DispatchableHandle handle, VkPhysicalDeviceLimits* limits, uint32_t* count,
                                                    VkExtensionProperties* props) {
        decltype(implementation)* func =
            reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
        if (func == nullptr) return VK_ERROR_DEVICE_LOST;
        VkResult res = func(handle, limits, count, props);
        if (props) {
            for (uint32_t i = 5; i < *count; i++) {
                props[i].specVersion = 1234 + i * 2;
            }
        } else if (count) {
            *count += 1;
        }
        return res;
    }

    template <typename ParentType>
    static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
                      uint32_t interception_count = 1) {
        decltype(implementation)* returned_func = loader.load(parent, name);
        ASSERT_NE(returned_func, nullptr);
        VkPhysicalDeviceLimits limits{};
        uint32_t count = 0;
        EXPECT_EQ(returned_func(dispatch_type, &limits, &count, nullptr), VK_INCOMPLETE);
        EXPECT_EQ(count, 5 + interception_count);
        std::vector<VkExtensionProperties> props(count, VkExtensionProperties{});
        EXPECT_EQ(returned_func(dispatch_type, &limits, &count, props.data()), VK_SUCCESS);
        for (uint32_t i = 0; i < 5; i++) {
            EXPECT_EQ(props.at(i).specVersion, i);
        }
        for (uint32_t i = 5; i < interception_count; i++) {
            EXPECT_EQ(props.at(i).specVersion, 1234 + i * 2);  // interception should do this
        }
    }
    template <typename ParentType>
    static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
                                        const char* name) {
        decltype(implementation)* returned_func = loader.load(parent, name);
        ASSERT_NE(returned_func, nullptr);
        VkPhysicalDeviceLimits limits{};
        EXPECT_EQ(returned_func(dispatch_type, &limits, nullptr, nullptr), VK_ERROR_DEVICE_LOST);
    }
};

struct UnknownFunction {
    std::string name;

    bool has_implementation = false;
    std::vector<uint32_t> interception_stack;

    UnknownFunction() = default;
    UnknownFunction(std::string name) : name(name) {}

    template <typename FunctionType, typename ParentType, typename DispatchableHandle>
    void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type) {
        if (has_implementation) {
            // Find how many layers intercept this function, stop if any layer 'implements' the function, thus doesn't return
            uint32_t intercept_count = 0;
            for (auto const& elem : interception_stack) {
                if (elem == 1) break;
                intercept_count++;
            }
            FunctionType::Function::check(loader, parent, dispatch_type, name.c_str(), intercept_count);
        } else {
            FunctionType::Function::check_no_implementation(loader, parent, dispatch_type, name.c_str());
        }
    }

    void push_layer_implementation() { interception_stack.push_back(1); }
    void push_layer_interception() { interception_stack.push_back(0); }
};

// For VkDevice, VkCommandBuffer, & VkQueue
template <typename FunctionType, typename DispatchableHandle>
struct UnknownFunctionInfo {
    using Function = FunctionType;

    static void add_to_driver(UnknownFunction& func, PhysicalDevice& physical_device) {
        physical_device.add_device_function({func.name.c_str(), to_vkVoidFunction(Function::implementation)});
        func.has_implementation = true;
    }

    template <typename LayerStruct>
    static void add_to_layer(UnknownFunction& func, TestLayer& layer, LayerStruct) {
        LayerInterceptData<LayerStruct>::layer = &layer;
        LayerInterceptData<LayerStruct>::name = func.name.c_str();
        layer.add_custom_device_interception_function(
            func.name, to_vkVoidFunction(&Function::template intercept<LayerInterceptData<LayerStruct>>));
        func.push_layer_interception();
    }

    static void add_implementation_to_layer(UnknownFunction& func, TestLayer& layer) {
        layer.add_custom_device_implementation_function({func.name.c_str(), to_vkVoidFunction(Function::implementation)});
        func.has_implementation = true;
        func.push_layer_implementation();
    }
};

// Specialization for VkPhysicalDevice

template <typename FunctionType>
struct UnknownFunctionInfo<FunctionType, VkPhysicalDevice> {
    using Function = FunctionType;

    static void add_to_driver(UnknownFunction& func, PhysicalDevice& physical_device) {
        physical_device.add_custom_physical_device_function({func.name.c_str(), to_vkVoidFunction(Function::implementation)});
        func.has_implementation = true;
    }

    template <typename LayerStruct>
    static void add_to_layer(UnknownFunction& func, TestLayer& layer, LayerStruct) {
        LayerInterceptData<LayerStruct>::layer = &layer;
        LayerInterceptData<LayerStruct>::name = func.name.c_str();
        layer.add_custom_physical_device_intercept_function(
            func.name, to_vkVoidFunction(&Function::template intercept<LayerInterceptData<LayerStruct>>));
        func.push_layer_interception();
    }

    static void add_implementation_to_layer(UnknownFunction& func, TestLayer& layer) {
        layer.add_custom_physical_device_implementation_function({func.name.c_str(), to_vkVoidFunction(Function::implementation)});
        func.has_implementation = true;
        func.push_layer_implementation();
    }
};

struct Functions {
    template <template <typename> class Function>
    struct HelperTypedef {
        using physical_device = UnknownFunctionInfo<Function<VkPhysicalDevice>, VkPhysicalDevice>;
        using device = UnknownFunctionInfo<Function<VkDevice>, VkDevice>;
        using command_buffer = UnknownFunctionInfo<Function<VkCommandBuffer>, VkCommandBuffer>;
        using queue = UnknownFunctionInfo<Function<VkQueue>, VkQueue>;
    };

    using zero = HelperTypedef<FunctionZero>;
    using one = HelperTypedef<FunctionOne>;
    using two = HelperTypedef<FunctionTwo>;
    using three = HelperTypedef<FunctionThree>;
    using four = HelperTypedef<FunctionFour>;
};

template <size_t I>
struct D {};

TEST(UnknownFunction, PhysicalDeviceFunctionTwoLayerInterception) {
    FrameworkEnvironment env{};
    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
    PhysicalDevice& pd = driver.physical_devices.back();

    UnknownFunction f{"vkFunc1"};
    Functions::three::physical_device::add_to_driver(f, pd);

    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
                                                         .set_disable_environment("DISABLE_ME")),
                           "implicit_layer_unknown_function_intercept.json");
    auto& layer0 = env.get_test_layer(0);
    Functions::three::physical_device::add_to_layer(f, layer0, D<0>{});

    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept2")
                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
                                                         .set_disable_environment("DISABLE_ME")),
                           "implicit_layer_unknown_function_intercept2.json");
    auto& layer1 = env.get_test_layer(1);

    Functions::three::physical_device::add_to_layer(f, layer1, D<1>{});

    InstWrapper inst{env.vulkan_functions};
    inst.CheckCreate();

    VkPhysicalDevice phys_dev = inst.GetPhysDev();

    f.check<Functions::three::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
}

TEST(UnknownFunction, ManyCombinations) {
    FrameworkEnvironment env{};
    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
    PhysicalDevice& physical_device = driver.physical_devices.back();
    std::vector<UnknownFunction> unknown_funcs;

    unknown_funcs.emplace_back("vkZero_uint32_uint32_0");
    unknown_funcs.emplace_back("vkOne_uint32_uint32_char_1");
    unknown_funcs.emplace_back("vkTwo_ptr_int_ptr_int_2");
    unknown_funcs.emplace_back("vkThree_ptr_int_ptr_float_uint_3");
    unknown_funcs.emplace_back("vkFour_PD_limits_ptr_uint_ptr_ExtProps_4");
    unknown_funcs.emplace_back("vkZero_uint32_uint32_5");
    unknown_funcs.emplace_back("vkOne_uint32_uint32_char_6");
    unknown_funcs.emplace_back("vkTwo_ptr_int_ptr_int_7");
    unknown_funcs.emplace_back("vkThree_ptr_int_ptr_float_uint_8");
    unknown_funcs.emplace_back("vkFour_PD_limits_ptr_uint_ptr_ExtProps_9");
    unknown_funcs.emplace_back("vkZero_uint32_uint32_10");
    unknown_funcs.emplace_back("vkOne_uint32_uint32_char_11");
    unknown_funcs.emplace_back("vkTwo_ptr_int_ptr_int_12");

    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_0")
                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
                                                         .set_disable_environment("DISABLE_ME")
                                                         .add_device_extension(ManifestLayer::LayerDescription::Extension{
                                                             "VK_EXT_for_the_laughs", 0, {"vkOne_uint32_uint32_char_11"}})),
                           "implicit_layer_unknown_function_intercept_0.json");
    auto& layer_0 = env.get_test_layer(0);
    layer_0.set_use_gipa_GetPhysicalDeviceProcAddr(true);
    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_1")
                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
                                                         .set_disable_environment("DISABLE_ME")),
                           "implicit_layer_unknown_function_intercept_1.json");
    auto& layer_1 = env.get_test_layer(1);
    layer_1.set_use_gipa_GetPhysicalDeviceProcAddr(false);

    // Physical Device functions
    Functions::zero::physical_device::add_to_driver(unknown_funcs.at(0), physical_device);

    Functions::one::physical_device::add_to_driver(unknown_funcs.at(1), physical_device);
    Functions::one::physical_device::add_to_layer(unknown_funcs.at(1), layer_0, D<0>{});

    Functions::two::physical_device::add_to_driver(unknown_funcs.at(2), physical_device);
    Functions::two::physical_device::add_to_layer(unknown_funcs.at(2), layer_1, D<1>{});

    Functions::three::physical_device::add_to_driver(unknown_funcs.at(3), physical_device);
    Functions::three::physical_device::add_to_layer(unknown_funcs.at(3), layer_0, D<2>{});
    Functions::three::physical_device::add_to_layer(unknown_funcs.at(3), layer_1, D<3>{});

    Functions::four::physical_device::add_implementation_to_layer(unknown_funcs.at(4), layer_0);
    Functions::four::physical_device::add_to_layer(unknown_funcs.at(4), layer_1, D<4>{});

    Functions::zero::physical_device::add_to_layer(unknown_funcs.at(5), layer_0, D<5>{});
    Functions::zero::physical_device::add_implementation_to_layer(unknown_funcs.at(5), layer_1);

    Functions::two::physical_device::add_to_driver(unknown_funcs.at(12), physical_device);
    Functions::zero::physical_device::add_to_layer(unknown_funcs.at(12), layer_0, D<12>{});
    Functions::zero::physical_device::add_implementation_to_layer(unknown_funcs.at(12), layer_1);

    // Device functions
    Functions::one::device::add_to_driver(unknown_funcs.at(6), physical_device);

    Functions::two::device::add_to_driver(unknown_funcs.at(7), physical_device);
    Functions::two::device::add_to_layer(unknown_funcs.at(7), layer_0, D<6>{});

    Functions::three::device::add_to_driver(unknown_funcs.at(8), physical_device);
    Functions::three::device::add_to_layer(unknown_funcs.at(8), layer_1, D<7>{});

    Functions::four::device::add_to_driver(unknown_funcs.at(9), physical_device);
    Functions::four::device::add_to_layer(unknown_funcs.at(9), layer_0, D<8>{});
    Functions::four::device::add_to_layer(unknown_funcs.at(9), layer_1, D<9>{});

    Functions::zero::device::add_implementation_to_layer(unknown_funcs.at(10), layer_0);
    Functions::zero::device::add_to_layer(unknown_funcs.at(10), layer_1, D<10>{});

    Functions::one::device::add_to_layer(unknown_funcs.at(11), layer_0, D<11>{});
    Functions::one::device::add_implementation_to_layer(unknown_funcs.at(11), layer_1);

    {
        InstWrapper inst{env.vulkan_functions};
        inst.CheckCreate();

        VkPhysicalDevice phys_dev = inst.GetPhysDev();
        DeviceWrapper dev{inst};
        dev.CheckCreate(phys_dev);

        unknown_funcs.at(0).check<Functions::zero::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
        unknown_funcs.at(1).check<Functions::one::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
        unknown_funcs.at(2).check<Functions::two::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
        unknown_funcs.at(3).check<Functions::three::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
        unknown_funcs.at(4).check<Functions::four::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
        unknown_funcs.at(5).check<Functions::zero::physical_device>(env.vulkan_functions, inst.inst, phys_dev);

        // Check that GIPA works for device functions
        unknown_funcs.at(6).check<Functions::one::device>(env.vulkan_functions, inst.inst, dev.dev);
        unknown_funcs.at(7).check<Functions::two::device>(env.vulkan_functions, inst.inst, dev.dev);
        unknown_funcs.at(8).check<Functions::three::device>(env.vulkan_functions, inst.inst, dev.dev);
        unknown_funcs.at(9).check<Functions::four::device>(env.vulkan_functions, inst.inst, dev.dev);
        unknown_funcs.at(10).check<Functions::zero::device>(env.vulkan_functions, inst.inst, dev.dev);
        unknown_funcs.at(11).check<Functions::one::device>(env.vulkan_functions, inst.inst, dev.dev);

        // Check that GDPA works for device functions
        unknown_funcs.at(6).check<Functions::one::device>(env.vulkan_functions, dev.dev, dev.dev);
        unknown_funcs.at(7).check<Functions::two::device>(env.vulkan_functions, dev.dev, dev.dev);
        unknown_funcs.at(8).check<Functions::three::device>(env.vulkan_functions, dev.dev, dev.dev);
        unknown_funcs.at(9).check<Functions::four::device>(env.vulkan_functions, dev.dev, dev.dev);
        unknown_funcs.at(10).check<Functions::zero::device>(env.vulkan_functions, dev.dev, dev.dev);
        unknown_funcs.at(11).check<Functions::one::device>(env.vulkan_functions, dev.dev, dev.dev);
    }

    {
        InstWrapper inst{env.vulkan_functions};
        inst.CheckCreate();

        VkPhysicalDevice phys_dev = inst.GetPhysDev();
        DeviceWrapper dev{inst};
        dev.CheckCreate(phys_dev);
        // Load device functions first, to make sure order of function loading is not important
        // Check that GIPA works for device functions
        unknown_funcs.at(6).check<Functions::one::device>(env.vulkan_functions, inst.inst, dev.dev);
        unknown_funcs.at(7).check<Functions::two::device>(env.vulkan_functions, inst.inst, dev.dev);
        unknown_funcs.at(8).check<Functions::three::device>(env.vulkan_functions, inst.inst, dev.dev);
        unknown_funcs.at(9).check<Functions::four::device>(env.vulkan_functions, inst.inst, dev.dev);
        unknown_funcs.at(10).check<Functions::zero::device>(env.vulkan_functions, inst.inst, dev.dev);
        unknown_funcs.at(11).check<Functions::one::device>(env.vulkan_functions, inst.inst, dev.dev);

        // Check that GDPA works for device functions
        unknown_funcs.at(6).check<Functions::one::device>(env.vulkan_functions, dev.dev, dev.dev);
        unknown_funcs.at(7).check<Functions::two::device>(env.vulkan_functions, dev.dev, dev.dev);
        unknown_funcs.at(8).check<Functions::three::device>(env.vulkan_functions, dev.dev, dev.dev);
        unknown_funcs.at(9).check<Functions::four::device>(env.vulkan_functions, dev.dev, dev.dev);
        unknown_funcs.at(10).check<Functions::zero::device>(env.vulkan_functions, dev.dev, dev.dev);
        unknown_funcs.at(11).check<Functions::one::device>(env.vulkan_functions, dev.dev, dev.dev);

        unknown_funcs.at(0).check<Functions::zero::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
        unknown_funcs.at(1).check<Functions::one::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
        unknown_funcs.at(2).check<Functions::two::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
        unknown_funcs.at(3).check<Functions::three::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
        unknown_funcs.at(4).check<Functions::four::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
        unknown_funcs.at(5).check<Functions::zero::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
    }
}

TEST(UnknownFunction, PhysicalDeviceFunctionInLayer) {
    FrameworkEnvironment env{};
    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});

    env.add_implicit_layer(ManifestLayer{}
                               .add_layer(ManifestLayer::LayerDescription{}
                                              .set_name("VK_LAYER_implicit_layer_1")
                                              .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_0)
                                              .set_disable_environment("DISABLE_ME"))
                               .set_file_format_version({1, 0, 0}),
                           "implicit_layer_1.json");

    UnknownFunction unknown_func{"vkPhysicalDeviceFunctionInLayer"};
    const char* ext_name = "VK_EXT_not_funny";

    const char* explicit_layer_unknown_function_implement = "VK_LAYER_implement_unknown_function";
    env.add_explicit_layer(
        ManifestLayer{}
            .add_layer(ManifestLayer::LayerDescription{}
                           .set_name(explicit_layer_unknown_function_implement)
                           .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
                           .add_instance_extension(ManifestLayer::LayerDescription::Extension{ext_name, 0, {unknown_func.name}}))
            .set_file_format_version({1, 1, 0}),
        "implement_unknown_function.json");
    auto& layer0 = env.get_test_layer(1);

    const char* explicit_layer_to_enable_1 = "VK_LAYER_explicit_layer_1";
    env.add_explicit_layer(ManifestLayer{}
                               .add_layer(ManifestLayer::LayerDescription{}
                                              .set_name(explicit_layer_to_enable_1)
                                              .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2))
                               .set_file_format_version({1, 2, 0}),
                           "explicit_layer_2.json");

    Functions::four::physical_device::add_implementation_to_layer(unknown_func, layer0);

    InstWrapper inst{env.vulkan_functions};
    inst.create_info.add_layer(explicit_layer_to_enable_1);
    inst.create_info.add_layer(explicit_layer_unknown_function_implement);
    inst.CheckCreate();

    VkPhysicalDevice phys_dev = inst.GetPhysDev();

    unknown_func.check<Functions::four::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
}
