15db71995Sopenharmony_ci/*
25db71995Sopenharmony_ci * Copyright (c) 2021 The Khronos Group Inc.
35db71995Sopenharmony_ci * Copyright (c) 2021 Valve Corporation
45db71995Sopenharmony_ci * Copyright (c) 2021 LunarG, Inc.
55db71995Sopenharmony_ci *
65db71995Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
75db71995Sopenharmony_ci * of this software and/or associated documentation files (the "Materials"), to
85db71995Sopenharmony_ci * deal in the Materials without restriction, including without limitation the
95db71995Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
105db71995Sopenharmony_ci * sell copies of the Materials, and to permit persons to whom the Materials are
115db71995Sopenharmony_ci * furnished to do so, subject to the following conditions:
125db71995Sopenharmony_ci *
135db71995Sopenharmony_ci * The above copyright notice(s) and this permission notice shall be included in
145db71995Sopenharmony_ci * all copies or substantial portions of the Materials.
155db71995Sopenharmony_ci *
165db71995Sopenharmony_ci * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
175db71995Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
185db71995Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
195db71995Sopenharmony_ci *
205db71995Sopenharmony_ci * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
215db71995Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
225db71995Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
235db71995Sopenharmony_ci * USE OR OTHER DEALINGS IN THE MATERIALS.
245db71995Sopenharmony_ci *
255db71995Sopenharmony_ci * Author: Charles Giessen <charles@lunarg.com>
265db71995Sopenharmony_ci */
275db71995Sopenharmony_ci
285db71995Sopenharmony_ci#include "test_environment.h"
295db71995Sopenharmony_ci#include <functional>
305db71995Sopenharmony_ci#include <tuple>
315db71995Sopenharmony_ci
325db71995Sopenharmony_cienum class TestConfig {
335db71995Sopenharmony_ci    add_layer_implementation,
345db71995Sopenharmony_ci    add_layer_interception,
355db71995Sopenharmony_ci};
365db71995Sopenharmony_ci
375db71995Sopenharmony_cibool has_flag(std::vector<TestConfig> const& flags, TestConfig config) {
385db71995Sopenharmony_ci    for (auto const& flag : flags)
395db71995Sopenharmony_ci        if (flag == config) return true;
405db71995Sopenharmony_ci    return false;
415db71995Sopenharmony_ci}
425db71995Sopenharmony_ci
435db71995Sopenharmony_ci/*
445db71995Sopenharmony_ci Creates a TestICD with a function unknown to the loader called vkNotRealFuncTEST. The TestICD, when
455db71995Sopenharmony_ci vk_icdGetPhysicalDeviceProcAddr is called, will return the custom_physical_device_function if the function name matches
465db71995Sopenharmony_ci vkNotRealFuncTEST. The test then calls the function to verify that the unknown physical device function dispatching is
475db71995Sopenharmony_ci working correctly.
485db71995Sopenharmony_ci*/
495db71995Sopenharmony_citemplate <typename DispatchableHandleType>
505db71995Sopenharmony_cistruct custom_functions {
515db71995Sopenharmony_ci    static VKAPI_ATTR uint32_t VKAPI_CALL func_zero(DispatchableHandleType, uint32_t foo) { return foo; };
525db71995Sopenharmony_ci    static VKAPI_ATTR uint32_t VKAPI_CALL func_one(DispatchableHandleType, uint32_t foo, uint32_t bar) { return foo + bar; };
535db71995Sopenharmony_ci    static VKAPI_ATTR float VKAPI_CALL func_two(DispatchableHandleType, uint32_t foo, uint32_t bar, float baz) {
545db71995Sopenharmony_ci        return baz + foo + bar;
555db71995Sopenharmony_ci    };
565db71995Sopenharmony_ci    static VKAPI_ATTR int VKAPI_CALL func_three(DispatchableHandleType, int* ptr_a, int* ptr_b) { return *ptr_a + *ptr_b; };
575db71995Sopenharmony_ci    static VKAPI_ATTR float VKAPI_CALL func_four(DispatchableHandleType, int* ptr_a, int* ptr_b, int foo, int bar, float k, float l,
585db71995Sopenharmony_ci                                                 char a, char b, char c) {
595db71995Sopenharmony_ci        return *ptr_a + *ptr_b + foo + bar + k + l + static_cast<int>(a) + static_cast<int>(b) + static_cast<int>(c);
605db71995Sopenharmony_ci    };
615db71995Sopenharmony_ci};
625db71995Sopenharmony_ci
635db71995Sopenharmony_ci/*
645db71995Sopenharmony_ciFunctions for testing of layer interception of unknown functions. Note the need to pass a pointer to the layer and the name
655db71995Sopenharmony_ciof the called function as a parameter, this is necessary to allow a generic layer implementation, as the layer must look up
665db71995Sopenharmony_cithe function pointer to use. A real layer would store the function pointer in a dedicated structure per-instance/device, but
675db71995Sopenharmony_cisince the TestLayer is a generic layer, there isn't a fixed list of functions that should be supported.
685db71995Sopenharmony_ci*/
695db71995Sopenharmony_ci
705db71995Sopenharmony_ciPFN_vkVoidFunction find_custom_func(TestLayer* layer, const char* name) {
715db71995Sopenharmony_ci    if (layer->custom_dispatch_functions.count(name) > 0) {
725db71995Sopenharmony_ci        return layer->custom_dispatch_functions.at(name);
735db71995Sopenharmony_ci    }
745db71995Sopenharmony_ci    return nullptr;
755db71995Sopenharmony_ci}
765db71995Sopenharmony_ci
775db71995Sopenharmony_citemplate <typename DispatchableHandleType>
785db71995Sopenharmony_cistruct layer_intercept_functions {
795db71995Sopenharmony_ci    static VKAPI_ATTR uint32_t VKAPI_CALL func_zero(DispatchableHandleType handle, TestLayer* layer, const char* name, uint32_t i) {
805db71995Sopenharmony_ci        auto func = reinterpret_cast<decltype(&func_zero)>(find_custom_func(layer, name));
815db71995Sopenharmony_ci        if (func == nullptr) return 1337;
825db71995Sopenharmony_ci        return func(handle, layer, name, i + 3);
835db71995Sopenharmony_ci    }
845db71995Sopenharmony_ci    static VKAPI_ATTR uint32_t VKAPI_CALL func_one(DispatchableHandleType handle, TestLayer* layer, const char* name, uint32_t i,
855db71995Sopenharmony_ci                                                   float f) {
865db71995Sopenharmony_ci        auto func = reinterpret_cast<decltype(&func_one)>(find_custom_func(layer, name));
875db71995Sopenharmony_ci        if (func == nullptr) return 1337;
885db71995Sopenharmony_ci        return func(handle, layer, name, i + 2, f + 1.f);
895db71995Sopenharmony_ci    }
905db71995Sopenharmony_ci    static VKAPI_ATTR float VKAPI_CALL func_two(DispatchableHandleType handle, TestLayer* layer, const char* name, uint32_t foo,
915db71995Sopenharmony_ci                                                uint32_t bar, float baz) {
925db71995Sopenharmony_ci        auto func = reinterpret_cast<decltype(&func_two)>(find_custom_func(layer, name));
935db71995Sopenharmony_ci        if (func == nullptr) return -1337;
945db71995Sopenharmony_ci        return func(handle, layer, name, foo + 1, bar + 2, baz * 2);
955db71995Sopenharmony_ci    };
965db71995Sopenharmony_ci    static VKAPI_ATTR int VKAPI_CALL func_three(DispatchableHandleType handle, TestLayer* layer, const char* name, int* ptr_a,
975db71995Sopenharmony_ci                                                int* ptr_b) {
985db71995Sopenharmony_ci        auto func = reinterpret_cast<decltype(&func_three)>(find_custom_func(layer, name));
995db71995Sopenharmony_ci        if (func == nullptr) return -1337;
1005db71995Sopenharmony_ci        *ptr_a += 1;
1015db71995Sopenharmony_ci        *ptr_b -= 2;
1025db71995Sopenharmony_ci        return func(handle, layer, name, ptr_a, ptr_b);
1035db71995Sopenharmony_ci    };
1045db71995Sopenharmony_ci    static VKAPI_ATTR float VKAPI_CALL func_four(DispatchableHandleType handle, TestLayer* layer, const char* name, int* ptr_a,
1055db71995Sopenharmony_ci                                                 int* ptr_b, int foo, int bar, float k, float l, char, char, char) {
1065db71995Sopenharmony_ci        auto func = reinterpret_cast<decltype(&func_four)>(find_custom_func(layer, name));
1075db71995Sopenharmony_ci        if (func == nullptr) return -1337.f;
1085db71995Sopenharmony_ci        return func(handle, layer, name, ptr_a, ptr_b, foo + 4, bar + 5, k + 1, l + 2, 'd', 'e', 'f');
1095db71995Sopenharmony_ci    };
1105db71995Sopenharmony_ci};
1115db71995Sopenharmony_ci
1125db71995Sopenharmony_citemplate <typename DispatchableHandleType>
1135db71995Sopenharmony_cistruct layer_implementation_functions {
1145db71995Sopenharmony_ci    static VKAPI_ATTR uint32_t VKAPI_CALL func_zero(DispatchableHandleType, TestLayer*, const char*, uint32_t i) { return i * 3; }
1155db71995Sopenharmony_ci    static VKAPI_ATTR uint32_t VKAPI_CALL func_one(DispatchableHandleType, TestLayer*, const char*, uint32_t i, float f) {
1165db71995Sopenharmony_ci        return static_cast<int>(i * 3 + f * 10.f);
1175db71995Sopenharmony_ci    }
1185db71995Sopenharmony_ci    static VKAPI_ATTR float VKAPI_CALL func_two(DispatchableHandleType, TestLayer*, const char*, uint32_t foo, uint32_t bar,
1195db71995Sopenharmony_ci                                                float baz) {
1205db71995Sopenharmony_ci        return baz + foo + bar;
1215db71995Sopenharmony_ci    };
1225db71995Sopenharmony_ci    static VKAPI_ATTR int VKAPI_CALL func_three(DispatchableHandleType, TestLayer*, const char*, int* ptr_a, int* ptr_b) {
1235db71995Sopenharmony_ci        return *ptr_a + *ptr_b;
1245db71995Sopenharmony_ci    };
1255db71995Sopenharmony_ci    static VKAPI_ATTR float VKAPI_CALL func_four(DispatchableHandleType, TestLayer*, const char*, int* ptr_a, int* ptr_b, int foo,
1265db71995Sopenharmony_ci                                                 int bar, float k, float l, char a, char b, char c) {
1275db71995Sopenharmony_ci        return *ptr_a + *ptr_b + foo + bar + k + l + static_cast<int>(a) + static_cast<int>(b) + static_cast<int>(c);
1285db71995Sopenharmony_ci    };
1295db71995Sopenharmony_ci};
1305db71995Sopenharmony_ci
1315db71995Sopenharmony_ci// Add function_count strings to the func_names vector, starting at function_start place. Essentially a utility for filling
1325db71995Sopenharmony_ci// up a list of names to use later
1335db71995Sopenharmony_civoid add_function_names(std::vector<std::string>& func_names, uint32_t function_count, uint32_t function_start = 0) {
1345db71995Sopenharmony_ci    for (uint32_t i = function_start; i < function_start + function_count;) {
1355db71995Sopenharmony_ci        func_names.push_back(std::string("vkNotIntRealFuncTEST_") + std::to_string(i++));
1365db71995Sopenharmony_ci        func_names.push_back(std::string("vkNotIntRealIntFuncTEST_") + std::to_string(i++));
1375db71995Sopenharmony_ci        func_names.push_back(std::string("vkIntNotIntRealFloatFuncTEST_") + std::to_string(i++));
1385db71995Sopenharmony_ci        func_names.push_back(std::string("vkNotRealFuncPointerPointerTEST_") + std::to_string(i++));
1395db71995Sopenharmony_ci        func_names.push_back(std::string("vkNotRealFuncTEST_pointer_pointer_int_int_float_float_char_char_char_") +
1405db71995Sopenharmony_ci                             std::to_string(i++));
1415db71995Sopenharmony_ci    }
1425db71995Sopenharmony_ci}
1435db71995Sopenharmony_ci
1445db71995Sopenharmony_ci// Add data to the function_list, which could be a driver or a layer list of implementation functions.
1455db71995Sopenharmony_citemplate <typename FunctionStruct>
1465db71995Sopenharmony_civoid fill_implementation_functions(std::vector<VulkanFunction>& function_list, std::vector<std::string>& func_names,
1475db71995Sopenharmony_ci                                   FunctionStruct const& funcs, uint32_t function_count, uint32_t function_start = 0) {
1485db71995Sopenharmony_ci    for (uint32_t i = function_start; i < function_start + function_count;) {
1495db71995Sopenharmony_ci        function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_zero)});
1505db71995Sopenharmony_ci        function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_one)});
1515db71995Sopenharmony_ci        function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_two)});
1525db71995Sopenharmony_ci        function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_three)});
1535db71995Sopenharmony_ci        function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_four)});
1545db71995Sopenharmony_ci    }
1555db71995Sopenharmony_ci}
1565db71995Sopenharmony_ci
1575db71995Sopenharmony_ci// Add device interception functions to a layer. Need to call `add_custom_device_interception_function` since the layer has
1585db71995Sopenharmony_ci// to setup a unordered_map for storing the next function in the chain, and key it based on the name
1595db71995Sopenharmony_citemplate <typename FunctionStruct>
1605db71995Sopenharmony_civoid fill_device_intercept_functions(TestLayer& layer, std::vector<std::string>& func_names, FunctionStruct const& funcs,
1615db71995Sopenharmony_ci                                     uint32_t function_count, uint32_t function_start = 0) {
1625db71995Sopenharmony_ci    for (uint32_t i = function_start; i < function_start + function_count;) {
1635db71995Sopenharmony_ci        layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_zero));
1645db71995Sopenharmony_ci        layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_one));
1655db71995Sopenharmony_ci        layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_two));
1665db71995Sopenharmony_ci        layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_three));
1675db71995Sopenharmony_ci        layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_four));
1685db71995Sopenharmony_ci    }
1695db71995Sopenharmony_ci}
1705db71995Sopenharmony_ci// Add physical device interception functions to a layer. Need to call `add_custom_device_interception_function` since the
1715db71995Sopenharmony_ci// layer has to setup a unordered_map for storing the next function in the chain, and key it based on the name
1725db71995Sopenharmony_citemplate <typename FunctionStruct>
1735db71995Sopenharmony_civoid fill_phys_dev_intercept_functions(TestLayer& layer, std::vector<std::string>& func_names, FunctionStruct const& funcs,
1745db71995Sopenharmony_ci                                       uint32_t function_count, uint32_t function_start = 0) {
1755db71995Sopenharmony_ci    for (uint32_t i = function_start; i < function_start + function_count;) {
1765db71995Sopenharmony_ci        layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_zero));
1775db71995Sopenharmony_ci        layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_one));
1785db71995Sopenharmony_ci        layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_two));
1795db71995Sopenharmony_ci        layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_three));
1805db71995Sopenharmony_ci        layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_four));
1815db71995Sopenharmony_ci    }
1825db71995Sopenharmony_ci}
1835db71995Sopenharmony_ci
1845db71995Sopenharmony_citemplate <typename FunctionLoader, typename ParentType, typename DispatchableHandleType, typename FunctionStruct>
1855db71995Sopenharmony_civoid check_custom_functions(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle, FunctionStruct const&,
1865db71995Sopenharmony_ci                            std::vector<std::string>& func_names, uint32_t function_count, uint32_t function_start = 0) {
1875db71995Sopenharmony_ci    for (uint32_t i = function_start; i < function_start + function_count;) {
1885db71995Sopenharmony_ci        decltype(FunctionStruct::func_zero)* returned_func_i = loader.load(parent, func_names.at(i++).c_str());
1895db71995Sopenharmony_ci        ASSERT_NE(returned_func_i, nullptr);
1905db71995Sopenharmony_ci        EXPECT_EQ(returned_func_i(handle, i * 10), i * 10);
1915db71995Sopenharmony_ci
1925db71995Sopenharmony_ci        decltype(FunctionStruct::func_one)* returned_func_ii = loader.load(parent, func_names.at(i++).c_str());
1935db71995Sopenharmony_ci        ASSERT_NE(returned_func_ii, nullptr);
1945db71995Sopenharmony_ci        EXPECT_EQ(returned_func_ii(handle, i * 10, i * 5), i * 10 + i * 5);
1955db71995Sopenharmony_ci
1965db71995Sopenharmony_ci        decltype(FunctionStruct::func_two)* returned_func_iif = loader.load(parent, func_names.at(i++).c_str());
1975db71995Sopenharmony_ci        ASSERT_NE(returned_func_iif, nullptr);
1985db71995Sopenharmony_ci        EXPECT_NEAR(returned_func_iif(handle, i * 10, i * 5, 0.1234f), i * 10 + i * 5 + 0.1234f, 0.001);
1995db71995Sopenharmony_ci
2005db71995Sopenharmony_ci        int x = 5;
2015db71995Sopenharmony_ci        int y = -505;
2025db71995Sopenharmony_ci        decltype(FunctionStruct::func_three)* returned_func_pp = loader.load(parent, func_names.at(i++).c_str());
2035db71995Sopenharmony_ci        ASSERT_NE(returned_func_pp, nullptr);
2045db71995Sopenharmony_ci        EXPECT_EQ(returned_func_pp(handle, &x, &y), -500);
2055db71995Sopenharmony_ci
2065db71995Sopenharmony_ci        x = 5;
2075db71995Sopenharmony_ci        y = -505;
2085db71995Sopenharmony_ci        decltype(FunctionStruct::func_four)* returned_func_ppiiffccc = loader.load(parent, func_names.at(i++).c_str());
2095db71995Sopenharmony_ci        ASSERT_NE(returned_func_ppiiffccc, nullptr);
2105db71995Sopenharmony_ci        EXPECT_NEAR(returned_func_ppiiffccc(handle, &x, &y, 200, 300, 0.123f, 1001.89f, 'a', 'b', 'c'),
2115db71995Sopenharmony_ci                    -500 + 200 + 300 + 0.123 + 1001.89 + 97 + 98 + 99, 0.001f);
2125db71995Sopenharmony_ci    }
2135db71995Sopenharmony_ci}
2145db71995Sopenharmony_ci
2155db71995Sopenharmony_citemplate <typename FunctionLoader, typename ParentType, typename DispatchableHandleType, typename FunctionStruct>
2165db71995Sopenharmony_civoid check_layer_custom_functions(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle, TestLayer& layer,
2175db71995Sopenharmony_ci                                  FunctionStruct const&, std::vector<std::string>& func_names, uint32_t function_count,
2185db71995Sopenharmony_ci                                  uint32_t function_start = 0) {
2195db71995Sopenharmony_ci    for (uint32_t i = function_start; i < function_start + function_count;) {
2205db71995Sopenharmony_ci        decltype(FunctionStruct::func_zero)* returned_func_i = loader.load(parent, func_names.at(i).c_str());
2215db71995Sopenharmony_ci        ASSERT_NE(returned_func_i, nullptr);
2225db71995Sopenharmony_ci        EXPECT_EQ(returned_func_i(handle, &layer, func_names.at(i).c_str(), i), (i + 3) * 3);
2235db71995Sopenharmony_ci        i++;
2245db71995Sopenharmony_ci        decltype(FunctionStruct::func_one)* returned_func_if = loader.load(parent, func_names.at(i).c_str());
2255db71995Sopenharmony_ci        ASSERT_NE(returned_func_if, nullptr);
2265db71995Sopenharmony_ci        EXPECT_EQ(returned_func_if(handle, &layer, func_names.at(i).c_str(), i, i + 1.f), (i + 2) * 3 + (i + 2) * 10);
2275db71995Sopenharmony_ci        i++;
2285db71995Sopenharmony_ci
2295db71995Sopenharmony_ci        decltype(FunctionStruct::func_two)* returned_func_iif = loader.load(parent, func_names.at(i).c_str());
2305db71995Sopenharmony_ci        ASSERT_NE(returned_func_iif, nullptr);
2315db71995Sopenharmony_ci        EXPECT_NEAR(returned_func_iif(handle, &layer, func_names.at(i).c_str(), i * 10, i * 5, 0.1234f),
2325db71995Sopenharmony_ci                    (i * 10 + 1) + (i * 5 + 2) + (0.1234f * 2.f), 0.001);
2335db71995Sopenharmony_ci        i++;
2345db71995Sopenharmony_ci
2355db71995Sopenharmony_ci        int x = 5 + i;
2365db71995Sopenharmony_ci        int y = -505 - i;
2375db71995Sopenharmony_ci        decltype(FunctionStruct::func_three)* returned_func_pp = loader.load(parent, func_names.at(i).c_str());
2385db71995Sopenharmony_ci        ASSERT_NE(returned_func_pp, nullptr);
2395db71995Sopenharmony_ci        EXPECT_EQ(returned_func_pp(handle, &layer, func_names.at(i).c_str(), &x, &y),
2405db71995Sopenharmony_ci                  (5 + static_cast<int>(i) + 1) + (-505 - static_cast<int>(i) - 2));
2415db71995Sopenharmony_ci        i++;
2425db71995Sopenharmony_ci
2435db71995Sopenharmony_ci        x = 5;
2445db71995Sopenharmony_ci        y = -505;
2455db71995Sopenharmony_ci        decltype(FunctionStruct::func_four)* returned_func_ppiiffccc = loader.load(parent, func_names.at(i).c_str());
2465db71995Sopenharmony_ci        ASSERT_NE(returned_func_ppiiffccc, nullptr);
2475db71995Sopenharmony_ci        EXPECT_NEAR(
2485db71995Sopenharmony_ci            returned_func_ppiiffccc(handle, &layer, func_names.at(i).c_str(), &x, &y, 200, 300, 0.123f, 1001.89f, 'a', 'b', 'c'),
2495db71995Sopenharmony_ci            -500 + (200 + 4) + (300 + 5) + (0.123 + 1) + (1001.89 + 2) + 100 + 101 + 102,
2505db71995Sopenharmony_ci            0.001f);  // layer changes abc to def
2515db71995Sopenharmony_ci        i++;
2525db71995Sopenharmony_ci    }
2535db71995Sopenharmony_ci}
2545db71995Sopenharmony_ci
2555db71995Sopenharmony_citemplate <typename FunctionLoader, typename ParentType, typename DispatchableHandleType, typename FunctionStruct>
2565db71995Sopenharmony_civoid check_layer_custom_functions_no_implementation(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle,
2575db71995Sopenharmony_ci                                                    TestLayer& layer, FunctionStruct const&, std::vector<std::string>& func_names,
2585db71995Sopenharmony_ci                                                    uint32_t function_count, uint32_t function_start = 0) {
2595db71995Sopenharmony_ci    for (uint32_t i = function_start; i < function_start + function_count;) {
2605db71995Sopenharmony_ci        decltype(FunctionStruct::func_zero)* returned_func_i = loader.load(parent, func_names.at(i).c_str());
2615db71995Sopenharmony_ci        ASSERT_NE(returned_func_i, nullptr);
2625db71995Sopenharmony_ci        EXPECT_EQ(1337U, returned_func_i(handle, &layer, func_names.at(i).c_str(), i));
2635db71995Sopenharmony_ci        i++;
2645db71995Sopenharmony_ci        decltype(FunctionStruct::func_one)* returned_func_if = loader.load(parent, func_names.at(i).c_str());
2655db71995Sopenharmony_ci        ASSERT_NE(returned_func_if, nullptr);
2665db71995Sopenharmony_ci        EXPECT_EQ(1337U, returned_func_if(handle, &layer, func_names.at(i).c_str(), i, i + 1.f));
2675db71995Sopenharmony_ci        i++;
2685db71995Sopenharmony_ci
2695db71995Sopenharmony_ci        decltype(FunctionStruct::func_two)* returned_func_iif = loader.load(parent, func_names.at(i).c_str());
2705db71995Sopenharmony_ci        ASSERT_NE(returned_func_iif, nullptr);
2715db71995Sopenharmony_ci        EXPECT_NEAR(-1337.0, returned_func_iif(handle, &layer, func_names.at(i).c_str(), i * 10, i * 5, 0.1234f), 0.001);
2725db71995Sopenharmony_ci        i++;
2735db71995Sopenharmony_ci
2745db71995Sopenharmony_ci        int x = 5 + i;
2755db71995Sopenharmony_ci        int y = -505 - i;
2765db71995Sopenharmony_ci        decltype(FunctionStruct::func_three)* returned_func_pp = loader.load(parent, func_names.at(i).c_str());
2775db71995Sopenharmony_ci        ASSERT_NE(returned_func_pp, nullptr);
2785db71995Sopenharmony_ci        EXPECT_EQ(-1337, returned_func_pp(handle, &layer, func_names.at(i).c_str(), &x, &y));
2795db71995Sopenharmony_ci        i++;
2805db71995Sopenharmony_ci
2815db71995Sopenharmony_ci        x = 5;
2825db71995Sopenharmony_ci        y = -505;
2835db71995Sopenharmony_ci        decltype(FunctionStruct::func_four)* returned_func_ppiiffccc = loader.load(parent, func_names.at(i).c_str());
2845db71995Sopenharmony_ci        ASSERT_NE(returned_func_ppiiffccc, nullptr);
2855db71995Sopenharmony_ci        EXPECT_NEAR(
2865db71995Sopenharmony_ci            -1337.0,
2875db71995Sopenharmony_ci            returned_func_ppiiffccc(handle, &layer, func_names.at(i).c_str(), &x, &y, 200, 300, 0.123f, 1001.89f, 'a', 'b', 'c'),
2885db71995Sopenharmony_ci            0.001);
2895db71995Sopenharmony_ci        i++;
2905db71995Sopenharmony_ci    }
2915db71995Sopenharmony_ci}
2925db71995Sopenharmony_ci
2935db71995Sopenharmony_citemplate <typename FunctionLoader, typename ParentType, typename DispatchableHandleType, typename FunctionStruct>
2945db71995Sopenharmony_civoid check_layer_custom_functions_no_interception(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle,
2955db71995Sopenharmony_ci                                                  TestLayer& layer, FunctionStruct const&, std::vector<std::string>& func_names,
2965db71995Sopenharmony_ci                                                  uint32_t function_count, uint32_t function_start = 0) {
2975db71995Sopenharmony_ci    for (uint32_t i = function_start; i < function_start + function_count;) {
2985db71995Sopenharmony_ci        decltype(FunctionStruct::func_zero)* returned_func_i = loader.load(parent, func_names.at(i).c_str());
2995db71995Sopenharmony_ci        ASSERT_NE(returned_func_i, nullptr);
3005db71995Sopenharmony_ci        EXPECT_EQ(returned_func_i(handle, &layer, func_names.at(i).c_str(), i), (i)*3);
3015db71995Sopenharmony_ci        i++;
3025db71995Sopenharmony_ci        decltype(FunctionStruct::func_one)* returned_func_if = loader.load(parent, func_names.at(i).c_str());
3035db71995Sopenharmony_ci        ASSERT_NE(returned_func_if, nullptr);
3045db71995Sopenharmony_ci        EXPECT_EQ(returned_func_if(handle, &layer, func_names.at(i).c_str(), i, i + 1.f), (i)*3 + (i + 1) * 10);
3055db71995Sopenharmony_ci        i++;
3065db71995Sopenharmony_ci
3075db71995Sopenharmony_ci        decltype(FunctionStruct::func_two)* returned_func_iif = loader.load(parent, func_names.at(i).c_str());
3085db71995Sopenharmony_ci        ASSERT_NE(returned_func_iif, nullptr);
3095db71995Sopenharmony_ci        EXPECT_NEAR(returned_func_iif(handle, &layer, func_names.at(i).c_str(), i * 10, i * 5, 0.1234f),
3105db71995Sopenharmony_ci                    (i * 10) + (i * 5) + (0.1234f), 0.001);
3115db71995Sopenharmony_ci        i++;
3125db71995Sopenharmony_ci
3135db71995Sopenharmony_ci        int x = 5 + i;
3145db71995Sopenharmony_ci        int y = -505 - i;
3155db71995Sopenharmony_ci        decltype(FunctionStruct::func_three)* returned_func_pp = loader.load(parent, func_names.at(i).c_str());
3165db71995Sopenharmony_ci        ASSERT_NE(returned_func_pp, nullptr);
3175db71995Sopenharmony_ci        EXPECT_EQ(returned_func_pp(handle, &layer, func_names.at(i).c_str(), &x, &y),
3185db71995Sopenharmony_ci                  (5 + static_cast<int>(i)) + (-505 - static_cast<int>(i)));
3195db71995Sopenharmony_ci        i++;
3205db71995Sopenharmony_ci
3215db71995Sopenharmony_ci        x = 5;
3225db71995Sopenharmony_ci        y = -505;
3235db71995Sopenharmony_ci        decltype(FunctionStruct::func_four)* returned_func_ppiiffccc = loader.load(parent, func_names.at(i).c_str());
3245db71995Sopenharmony_ci        ASSERT_NE(returned_func_ppiiffccc, nullptr);
3255db71995Sopenharmony_ci        EXPECT_NEAR(
3265db71995Sopenharmony_ci            returned_func_ppiiffccc(handle, &layer, func_names.at(i).c_str(), &x, &y, 200, 300, 0.123f, 1001.89f, 'a', 'b', 'c'),
3275db71995Sopenharmony_ci            -500 + (200) + (300) + (0.123) + (1001.89) + 97 + 98 + 99, 0.001f);
3285db71995Sopenharmony_ci        i++;
3295db71995Sopenharmony_ci    }
3305db71995Sopenharmony_ci}
3315db71995Sopenharmony_ci
3325db71995Sopenharmony_ciusing custom_physical_device_functions = custom_functions<VkPhysicalDevice>;
3335db71995Sopenharmony_ciusing layer_intercept_physical_device_functions = layer_intercept_functions<VkPhysicalDevice>;
3345db71995Sopenharmony_ciusing layer_implementation_physical_device_functions = layer_implementation_functions<VkPhysicalDevice>;
3355db71995Sopenharmony_ci
3365db71995Sopenharmony_ciTEST(UnknownFunction, PhysicalDeviceFunction) {
3375db71995Sopenharmony_ci    FrameworkEnvironment env{};
3385db71995Sopenharmony_ci    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
3395db71995Sopenharmony_ci    uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
3405db71995Sopenharmony_ci    std::vector<std::string> function_names;
3415db71995Sopenharmony_ci    add_function_names(function_names, function_count);
3425db71995Sopenharmony_ci
3435db71995Sopenharmony_ci    fill_implementation_functions(driver.physical_devices.at(0).custom_physical_device_functions, function_names,
3445db71995Sopenharmony_ci                                  custom_physical_device_functions{}, function_count);
3455db71995Sopenharmony_ci    InstWrapper inst{env.vulkan_functions};
3465db71995Sopenharmony_ci    inst.CheckCreate();
3475db71995Sopenharmony_ci
3485db71995Sopenharmony_ci    VkPhysicalDevice phys_dev = inst.GetPhysDev();
3495db71995Sopenharmony_ci    check_custom_functions(env.vulkan_functions, inst.inst, phys_dev, custom_physical_device_functions{}, function_names,
3505db71995Sopenharmony_ci                           function_count);
3515db71995Sopenharmony_ci}
3525db71995Sopenharmony_ci
3535db71995Sopenharmony_ciTEST(UnknownFunction, PhysicalDeviceFunctionMultipleDriverSupport) {
3545db71995Sopenharmony_ci    FrameworkEnvironment env{};
3555db71995Sopenharmony_ci    auto& driver_0 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3565db71995Sopenharmony_ci    auto& driver_1 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3575db71995Sopenharmony_ci    uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
3585db71995Sopenharmony_ci    std::vector<std::string> function_names;
3595db71995Sopenharmony_ci    add_function_names(function_names, function_count);
3605db71995Sopenharmony_ci
3615db71995Sopenharmony_ci    // used to identify the GPUs
3625db71995Sopenharmony_ci    driver_0.physical_devices.emplace_back("physical_device_0").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
3635db71995Sopenharmony_ci    driver_1.physical_devices.emplace_back("physical_device_1").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
3645db71995Sopenharmony_ci
3655db71995Sopenharmony_ci    for (uint32_t i = 0; i < function_count / 10; i++) {
3665db71995Sopenharmony_ci        fill_implementation_functions(driver_0.physical_devices.at(0).custom_physical_device_functions, function_names,
3675db71995Sopenharmony_ci                                      custom_physical_device_functions{}, 5, i * 10);
3685db71995Sopenharmony_ci        fill_implementation_functions(driver_1.physical_devices.at(0).custom_physical_device_functions, function_names,
3695db71995Sopenharmony_ci                                      custom_physical_device_functions{}, 5, i * 10 + 5);
3705db71995Sopenharmony_ci    }
3715db71995Sopenharmony_ci    InstWrapper inst{env.vulkan_functions};
3725db71995Sopenharmony_ci    inst.CheckCreate();
3735db71995Sopenharmony_ci
3745db71995Sopenharmony_ci    auto phys_devs = inst.GetPhysDevs(2);
3755db71995Sopenharmony_ci    VkPhysicalDevice phys_dev_0 = phys_devs[0];
3765db71995Sopenharmony_ci    VkPhysicalDevice phys_dev_1 = phys_devs[1];
3775db71995Sopenharmony_ci    VkPhysicalDeviceProperties props{};
3785db71995Sopenharmony_ci    env.vulkan_functions.vkGetPhysicalDeviceProperties(phys_devs[0], &props);
3795db71995Sopenharmony_ci    if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
3805db71995Sopenharmony_ci        phys_dev_0 = phys_devs[1];
3815db71995Sopenharmony_ci        phys_dev_1 = phys_devs[0];
3825db71995Sopenharmony_ci    }
3835db71995Sopenharmony_ci    for (uint32_t i = 0; i < function_count / 10; i++) {
3845db71995Sopenharmony_ci        check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_0, custom_physical_device_functions{}, function_names, 5,
3855db71995Sopenharmony_ci                               i * 10);
3865db71995Sopenharmony_ci        check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_1, custom_physical_device_functions{}, function_names, 5,
3875db71995Sopenharmony_ci                               i * 10 + 5);
3885db71995Sopenharmony_ci    }
3895db71995Sopenharmony_ci}
3905db71995Sopenharmony_ci
3915db71995Sopenharmony_ci// Add unknown functions to driver 0, and try to use them on driver 1.
3925db71995Sopenharmony_ciTEST(UnknownFunctionDeathTests, PhysicalDeviceFunctionErrorPath) {
3935db71995Sopenharmony_ci    FrameworkEnvironment env{};
3945db71995Sopenharmony_ci    auto& driver_0 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3955db71995Sopenharmony_ci    auto& driver_1 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
3965db71995Sopenharmony_ci    std::vector<std::string> function_names;
3975db71995Sopenharmony_ci    add_function_names(function_names, 1);
3985db71995Sopenharmony_ci
3995db71995Sopenharmony_ci    // used to identify the GPUs
4005db71995Sopenharmony_ci    driver_0.physical_devices.emplace_back("physical_device_0").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
4015db71995Sopenharmony_ci    driver_1.physical_devices.emplace_back("physical_device_1").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
4025db71995Sopenharmony_ci    function_names.push_back(std::string("vkNotIntRealFuncTEST_0"));
4035db71995Sopenharmony_ci
4045db71995Sopenharmony_ci    custom_physical_device_functions funcs{};
4055db71995Sopenharmony_ci    driver_0.physical_devices.at(0).custom_physical_device_functions.push_back(
4065db71995Sopenharmony_ci        VulkanFunction{function_names.back(), to_vkVoidFunction(funcs.func_zero)});
4075db71995Sopenharmony_ci
4085db71995Sopenharmony_ci    InstWrapper inst{env.vulkan_functions};
4095db71995Sopenharmony_ci    inst.CheckCreate();
4105db71995Sopenharmony_ci
4115db71995Sopenharmony_ci    auto phys_devs = inst.GetPhysDevs(2);
4125db71995Sopenharmony_ci    VkPhysicalDevice phys_dev_to_use = phys_devs[1];
4135db71995Sopenharmony_ci    VkPhysicalDeviceProperties props{};
4145db71995Sopenharmony_ci    env.vulkan_functions.vkGetPhysicalDeviceProperties(phys_devs[1], &props);
4155db71995Sopenharmony_ci    if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) phys_dev_to_use = phys_devs[0];
4165db71995Sopenharmony_ci    // use the wrong GPU to query the functions, should get 5 errors
4175db71995Sopenharmony_ci
4185db71995Sopenharmony_ci    decltype(custom_physical_device_functions::func_zero)* returned_func_i =
4195db71995Sopenharmony_ci        env.vulkan_functions.load(inst.inst, function_names.at(0).c_str());
4205db71995Sopenharmony_ci    ASSERT_NE(returned_func_i, nullptr);
4215db71995Sopenharmony_ci    ASSERT_DEATH(returned_func_i(phys_dev_to_use, 0), "Function vkNotIntRealFuncTEST_0 not supported for this physical device");
4225db71995Sopenharmony_ci}
4235db71995Sopenharmony_ci
4245db71995Sopenharmony_ciTEST(UnknownFunction, PhysicalDeviceFunctionWithImplicitLayerImplementation) {
4255db71995Sopenharmony_ci    FrameworkEnvironment env{};
4265db71995Sopenharmony_ci    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
4275db71995Sopenharmony_ci    uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
4285db71995Sopenharmony_ci    std::vector<std::string> function_names;
4295db71995Sopenharmony_ci    add_function_names(function_names, function_count);
4305db71995Sopenharmony_ci
4315db71995Sopenharmony_ci    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
4325db71995Sopenharmony_ci                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
4335db71995Sopenharmony_ci                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
4345db71995Sopenharmony_ci                                                         .set_disable_environment("DISABLE_ME")),
4355db71995Sopenharmony_ci                           "implicit_layer_unknown_function_intercept.json");
4365db71995Sopenharmony_ci    auto& layer = env.get_test_layer();
4375db71995Sopenharmony_ci    fill_implementation_functions(layer.custom_physical_device_implementation_functions, function_names,
4385db71995Sopenharmony_ci                                  layer_implementation_physical_device_functions{}, function_count);
4395db71995Sopenharmony_ci
4405db71995Sopenharmony_ci    InstWrapper inst{env.vulkan_functions};
4415db71995Sopenharmony_ci    inst.CheckCreate();
4425db71995Sopenharmony_ci
4435db71995Sopenharmony_ci    VkPhysicalDevice phys_dev = inst.GetPhysDev();
4445db71995Sopenharmony_ci    check_layer_custom_functions_no_interception(env.vulkan_functions, inst.inst, phys_dev, layer,
4455db71995Sopenharmony_ci                                                 layer_implementation_physical_device_functions{}, function_names, function_count);
4465db71995Sopenharmony_ci}
4475db71995Sopenharmony_ci
4485db71995Sopenharmony_ciTEST(UnknownFunction, PhysicalDeviceFunctionMultipleDriverSupportWithImplicitLayerImplementation) {
4495db71995Sopenharmony_ci    FrameworkEnvironment env{};
4505db71995Sopenharmony_ci    auto& driver_0 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4515db71995Sopenharmony_ci    auto& driver_1 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
4525db71995Sopenharmony_ci    uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
4535db71995Sopenharmony_ci    std::vector<std::string> function_names;
4545db71995Sopenharmony_ci    add_function_names(function_names, function_count);
4555db71995Sopenharmony_ci
4565db71995Sopenharmony_ci    // used to identify the GPUs
4575db71995Sopenharmony_ci    driver_0.physical_devices.emplace_back("physical_device_0").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
4585db71995Sopenharmony_ci    driver_1.physical_devices.emplace_back("physical_device_1").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
4595db71995Sopenharmony_ci    for (uint32_t i = 0; i < function_count / 10; i++) {
4605db71995Sopenharmony_ci        fill_implementation_functions(driver_0.physical_devices.at(0).custom_physical_device_functions, function_names,
4615db71995Sopenharmony_ci                                      custom_physical_device_functions{}, 5, i * 10);
4625db71995Sopenharmony_ci        fill_implementation_functions(driver_1.physical_devices.at(0).custom_physical_device_functions, function_names,
4635db71995Sopenharmony_ci                                      custom_physical_device_functions{}, 5, i * 10 + 5);
4645db71995Sopenharmony_ci    }
4655db71995Sopenharmony_ci
4665db71995Sopenharmony_ci    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
4675db71995Sopenharmony_ci                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
4685db71995Sopenharmony_ci                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
4695db71995Sopenharmony_ci                                                         .set_disable_environment("DISABLE_ME")),
4705db71995Sopenharmony_ci                           "implicit_layer_unknown_function_intercept.json");
4715db71995Sopenharmony_ci
4725db71995Sopenharmony_ci    InstWrapper inst{env.vulkan_functions};
4735db71995Sopenharmony_ci    inst.CheckCreate();
4745db71995Sopenharmony_ci
4755db71995Sopenharmony_ci    auto phys_devs = inst.GetPhysDevs(2);
4765db71995Sopenharmony_ci    VkPhysicalDevice phys_dev_0 = phys_devs[0];
4775db71995Sopenharmony_ci    VkPhysicalDevice phys_dev_1 = phys_devs[1];
4785db71995Sopenharmony_ci    VkPhysicalDeviceProperties props{};
4795db71995Sopenharmony_ci    env.vulkan_functions.vkGetPhysicalDeviceProperties(phys_devs[0], &props);
4805db71995Sopenharmony_ci    if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
4815db71995Sopenharmony_ci        phys_dev_0 = phys_devs[1];
4825db71995Sopenharmony_ci        phys_dev_1 = phys_devs[0];
4835db71995Sopenharmony_ci    }
4845db71995Sopenharmony_ci    for (uint32_t i = 0; i < function_count / 10; i++) {
4855db71995Sopenharmony_ci        check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_0, custom_physical_device_functions{}, function_names, 5,
4865db71995Sopenharmony_ci                               i * 10);
4875db71995Sopenharmony_ci        check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_1, custom_physical_device_functions{}, function_names, 5,
4885db71995Sopenharmony_ci                               i * 10 + 5);
4895db71995Sopenharmony_ci    }
4905db71995Sopenharmony_ci}
4915db71995Sopenharmony_ci
4925db71995Sopenharmony_ciTEST(UnknownFunction, PhysicalDeviceFunctionWithImplicitLayerInterception) {
4935db71995Sopenharmony_ci    FrameworkEnvironment env{};
4945db71995Sopenharmony_ci    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
4955db71995Sopenharmony_ci    uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
4965db71995Sopenharmony_ci
4975db71995Sopenharmony_ci    std::vector<std::string> function_names;
4985db71995Sopenharmony_ci    add_function_names(function_names, function_count);
4995db71995Sopenharmony_ci
5005db71995Sopenharmony_ci    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
5015db71995Sopenharmony_ci                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
5025db71995Sopenharmony_ci                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
5035db71995Sopenharmony_ci                                                         .set_disable_environment("DISABLE_ME")),
5045db71995Sopenharmony_ci                           "implicit_layer_unknown_function_intercept.json");
5055db71995Sopenharmony_ci    auto& layer = env.get_test_layer();
5065db71995Sopenharmony_ci    fill_phys_dev_intercept_functions(layer, function_names, layer_intercept_physical_device_functions{}, function_count);
5075db71995Sopenharmony_ci
5085db71995Sopenharmony_ci    InstWrapper inst{env.vulkan_functions};
5095db71995Sopenharmony_ci    inst.CheckCreate();
5105db71995Sopenharmony_ci
5115db71995Sopenharmony_ci    VkPhysicalDevice phys_dev = inst.GetPhysDev();
5125db71995Sopenharmony_ci    check_layer_custom_functions_no_implementation(env.vulkan_functions, inst.inst, phys_dev, layer,
5135db71995Sopenharmony_ci                                                   layer_intercept_physical_device_functions{}, function_names, function_count);
5145db71995Sopenharmony_ci}
5155db71995Sopenharmony_ci
5165db71995Sopenharmony_ciTEST(UnknownFunction, PhysicalDeviceFunctionDriverSupportWithImplicitLayerInterception) {
5175db71995Sopenharmony_ci    FrameworkEnvironment env{};
5185db71995Sopenharmony_ci    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
5195db71995Sopenharmony_ci    uint32_t function_count = 100;
5205db71995Sopenharmony_ci    std::vector<std::string> function_names;
5215db71995Sopenharmony_ci    add_function_names(function_names, function_count);
5225db71995Sopenharmony_ci    fill_implementation_functions(driver.physical_devices.at(0).custom_physical_device_functions, function_names,
5235db71995Sopenharmony_ci                                  layer_implementation_physical_device_functions{}, function_count);
5245db71995Sopenharmony_ci    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
5255db71995Sopenharmony_ci                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
5265db71995Sopenharmony_ci                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
5275db71995Sopenharmony_ci                                                         .set_disable_environment("DISABLE_ME")),
5285db71995Sopenharmony_ci                           "implicit_layer_unknown_function_intercept.json");
5295db71995Sopenharmony_ci    auto& layer = env.get_test_layer();
5305db71995Sopenharmony_ci    fill_phys_dev_intercept_functions(layer, function_names, layer_intercept_physical_device_functions{}, function_count);
5315db71995Sopenharmony_ci
5325db71995Sopenharmony_ci    InstWrapper inst{env.vulkan_functions};
5335db71995Sopenharmony_ci    inst.CheckCreate();
5345db71995Sopenharmony_ci
5355db71995Sopenharmony_ci    VkPhysicalDevice phys_dev = inst.GetPhysDev();
5365db71995Sopenharmony_ci    check_layer_custom_functions(env.vulkan_functions, inst.inst, phys_dev, layer, layer_intercept_physical_device_functions{},
5375db71995Sopenharmony_ci                                 function_names, function_count);
5385db71995Sopenharmony_ci}
5395db71995Sopenharmony_ci
5405db71995Sopenharmony_ciTEST(UnknownFunction, PhysicalDeviceFunctionWithMultipleImplicitLayersInterception) {
5415db71995Sopenharmony_ci    FrameworkEnvironment env{};
5425db71995Sopenharmony_ci    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
5435db71995Sopenharmony_ci    std::vector<std::string> function_names;
5445db71995Sopenharmony_ci    uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
5455db71995Sopenharmony_ci    add_function_names(function_names, function_count);
5465db71995Sopenharmony_ci    driver.physical_devices.emplace_back("physical_device_0");
5475db71995Sopenharmony_ci
5485db71995Sopenharmony_ci    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
5495db71995Sopenharmony_ci                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_0")
5505db71995Sopenharmony_ci                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
5515db71995Sopenharmony_ci                                                         .set_disable_environment("DISABLE_ME")),
5525db71995Sopenharmony_ci                           "implicit_layer_unknown_function_intercept_0.json");
5535db71995Sopenharmony_ci    auto& layer_0 = env.get_test_layer(0);
5545db71995Sopenharmony_ci    layer_0.set_use_gipa_GetPhysicalDeviceProcAddr(true);
5555db71995Sopenharmony_ci    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
5565db71995Sopenharmony_ci                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_1")
5575db71995Sopenharmony_ci                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
5585db71995Sopenharmony_ci                                                         .set_disable_environment("DISABLE_ME")),
5595db71995Sopenharmony_ci                           "implicit_layer_unknown_function_intercept_1.json");
5605db71995Sopenharmony_ci    auto& layer_1 = env.get_test_layer(1);
5615db71995Sopenharmony_ci    layer_1.set_use_gipa_GetPhysicalDeviceProcAddr(false);
5625db71995Sopenharmony_ci    for (uint32_t i = 0; i < function_count / 10; i++) {
5635db71995Sopenharmony_ci        fill_implementation_functions(driver.physical_devices.at(0).custom_physical_device_functions, function_names,
5645db71995Sopenharmony_ci                                      layer_implementation_physical_device_functions{}, 5, i * 10);
5655db71995Sopenharmony_ci        fill_phys_dev_intercept_functions(layer_0, function_names, layer_intercept_physical_device_functions{}, 5, i * 10);
5665db71995Sopenharmony_ci        fill_phys_dev_intercept_functions(layer_1, function_names, layer_intercept_physical_device_functions{}, 5, i * 10 + 5);
5675db71995Sopenharmony_ci    }
5685db71995Sopenharmony_ci    InstWrapper inst{env.vulkan_functions};
5695db71995Sopenharmony_ci    inst.CheckCreate();
5705db71995Sopenharmony_ci
5715db71995Sopenharmony_ci    VkPhysicalDevice phys_dev = inst.GetPhysDev();
5725db71995Sopenharmony_ci    for (uint32_t i = 0; i < function_count / 10; i++) {
5735db71995Sopenharmony_ci        check_layer_custom_functions(env.vulkan_functions, inst.inst, phys_dev, layer_0,
5745db71995Sopenharmony_ci                                     layer_intercept_physical_device_functions{}, function_names, 5, i * 10);
5755db71995Sopenharmony_ci        check_layer_custom_functions_no_implementation(env.vulkan_functions, inst.inst, phys_dev, layer_1,
5765db71995Sopenharmony_ci                                                       layer_intercept_physical_device_functions{}, function_names, 5, i * 10 + 5);
5775db71995Sopenharmony_ci    }
5785db71995Sopenharmony_ci}
5795db71995Sopenharmony_ci
5805db71995Sopenharmony_citemplate <typename ParentType>
5815db71995Sopenharmony_ciParentType get_parent_type(InstWrapper const& inst, DeviceWrapper const& dev);
5825db71995Sopenharmony_ci
5835db71995Sopenharmony_citemplate <>
5845db71995Sopenharmony_ciVkInstance get_parent_type<VkInstance>(InstWrapper const& inst, DeviceWrapper const&) {
5855db71995Sopenharmony_ci    return inst.inst;
5865db71995Sopenharmony_ci}
5875db71995Sopenharmony_citemplate <>
5885db71995Sopenharmony_ciVkDevice get_parent_type<VkDevice>(InstWrapper const&, DeviceWrapper const& dev) {
5895db71995Sopenharmony_ci    return dev.dev;
5905db71995Sopenharmony_ci}
5915db71995Sopenharmony_ci
5925db71995Sopenharmony_citemplate <typename DispatchableHandleType>
5935db71995Sopenharmony_ciDispatchableHandleType get_dispatch_handle(FrameworkEnvironment& env, DeviceWrapper const& dev,
5945db71995Sopenharmony_ci                                           std::vector<TestConfig> const& flags);
5955db71995Sopenharmony_ci
5965db71995Sopenharmony_citemplate <>
5975db71995Sopenharmony_ciVkDevice get_dispatch_handle<VkDevice>(FrameworkEnvironment&, DeviceWrapper const& dev, std::vector<TestConfig> const&) {
5985db71995Sopenharmony_ci    return dev.dev;
5995db71995Sopenharmony_ci}
6005db71995Sopenharmony_ci
6015db71995Sopenharmony_citemplate <>
6025db71995Sopenharmony_ciVkCommandBuffer get_dispatch_handle<VkCommandBuffer>(FrameworkEnvironment& env, DeviceWrapper const& dev,
6035db71995Sopenharmony_ci                                                     std::vector<TestConfig> const&) {
6045db71995Sopenharmony_ci    VkCommandPool command_pool;
6055db71995Sopenharmony_ci    VkCommandPoolCreateInfo pool_create_info{};
6065db71995Sopenharmony_ci    DeviceFunctions funcs{env.vulkan_functions, dev};
6075db71995Sopenharmony_ci    funcs.vkCreateCommandPool(dev, &pool_create_info, nullptr, &command_pool);
6085db71995Sopenharmony_ci    VkCommandBuffer command_buffer;
6095db71995Sopenharmony_ci    VkCommandBufferAllocateInfo alloc_info{};
6105db71995Sopenharmony_ci    alloc_info.commandBufferCount = 1;
6115db71995Sopenharmony_ci    alloc_info.commandPool = command_pool;
6125db71995Sopenharmony_ci    funcs.vkAllocateCommandBuffers(dev, &alloc_info, &command_buffer);
6135db71995Sopenharmony_ci    return command_buffer;
6145db71995Sopenharmony_ci}
6155db71995Sopenharmony_ci
6165db71995Sopenharmony_citemplate <>
6175db71995Sopenharmony_ciVkQueue get_dispatch_handle<VkQueue>(FrameworkEnvironment& env, DeviceWrapper const& dev, std::vector<TestConfig> const&) {
6185db71995Sopenharmony_ci    DeviceFunctions funcs{env.vulkan_functions, dev.dev};
6195db71995Sopenharmony_ci    VkQueue queue;
6205db71995Sopenharmony_ci    funcs.vkGetDeviceQueue(dev, 0, 0, &queue);
6215db71995Sopenharmony_ci    return queue;
6225db71995Sopenharmony_ci}
6235db71995Sopenharmony_ci
6245db71995Sopenharmony_citemplate <typename ParentType, typename DispatchableHandleType>
6255db71995Sopenharmony_civoid unknown_function_test_impl(std::vector<TestConfig> const& flags) {
6265db71995Sopenharmony_ci    using custom_functions_type = custom_functions<DispatchableHandleType>;
6275db71995Sopenharmony_ci    using layer_implementation_functions_type = layer_implementation_functions<DispatchableHandleType>;
6285db71995Sopenharmony_ci    using layer_intercept_functions_type = layer_intercept_functions<DispatchableHandleType>;
6295db71995Sopenharmony_ci
6305db71995Sopenharmony_ci    FrameworkEnvironment env{};
6315db71995Sopenharmony_ci    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
6325db71995Sopenharmony_ci    uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
6335db71995Sopenharmony_ci
6345db71995Sopenharmony_ci    std::vector<std::string> function_names;
6355db71995Sopenharmony_ci    add_function_names(function_names, function_count);
6365db71995Sopenharmony_ci
6375db71995Sopenharmony_ci    if (has_flag(flags, TestConfig::add_layer_interception)) {
6385db71995Sopenharmony_ci        fill_implementation_functions(driver.physical_devices.back().known_device_functions, function_names,
6395db71995Sopenharmony_ci                                      layer_implementation_functions_type{}, function_count);
6405db71995Sopenharmony_ci    } else {
6415db71995Sopenharmony_ci        fill_implementation_functions(driver.physical_devices.back().known_device_functions, function_names,
6425db71995Sopenharmony_ci                                      custom_functions_type{}, function_count);
6435db71995Sopenharmony_ci    }
6445db71995Sopenharmony_ci    TestLayer* layer_ptr = nullptr;
6455db71995Sopenharmony_ci    if (has_flag(flags, TestConfig::add_layer_implementation) || has_flag(flags, TestConfig::add_layer_interception)) {
6465db71995Sopenharmony_ci        env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
6475db71995Sopenharmony_ci                                                             .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
6485db71995Sopenharmony_ci                                                             .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
6495db71995Sopenharmony_ci                                                             .set_disable_environment("DISABLE_ME")),
6505db71995Sopenharmony_ci                               "implicit_layer_unknown_function_intercept.json");
6515db71995Sopenharmony_ci        layer_ptr = &env.get_test_layer();
6525db71995Sopenharmony_ci    }
6535db71995Sopenharmony_ci    if (has_flag(flags, TestConfig::add_layer_implementation) && has_flag(flags, TestConfig::add_layer_interception)) {
6545db71995Sopenharmony_ci        for (uint32_t i = 0; i < function_count / 10; i++) {
6555db71995Sopenharmony_ci            fill_implementation_functions(layer_ptr->custom_device_implementation_functions, function_names,
6565db71995Sopenharmony_ci                                          layer_implementation_functions_type{}, 5, i * 10);
6575db71995Sopenharmony_ci            fill_device_intercept_functions(*layer_ptr, function_names, layer_intercept_functions_type{}, 5, i * 10 + 5);
6585db71995Sopenharmony_ci        }
6595db71995Sopenharmony_ci    } else if (has_flag(flags, TestConfig::add_layer_implementation)) {
6605db71995Sopenharmony_ci        fill_implementation_functions(layer_ptr->custom_device_implementation_functions, function_names, custom_functions_type{},
6615db71995Sopenharmony_ci                                      function_count);
6625db71995Sopenharmony_ci    } else if (has_flag(flags, TestConfig::add_layer_interception)) {
6635db71995Sopenharmony_ci        fill_device_intercept_functions(*layer_ptr, function_names, layer_intercept_functions_type{}, function_count);
6645db71995Sopenharmony_ci    }
6655db71995Sopenharmony_ci
6665db71995Sopenharmony_ci    InstWrapper inst{env.vulkan_functions};
6675db71995Sopenharmony_ci    inst.CheckCreate();
6685db71995Sopenharmony_ci
6695db71995Sopenharmony_ci    DeviceWrapper dev{inst};
6705db71995Sopenharmony_ci    dev.create_info.add_device_queue({});
6715db71995Sopenharmony_ci    dev.CheckCreate(inst.GetPhysDev());
6725db71995Sopenharmony_ci    auto dispatch_type = get_dispatch_handle<DispatchableHandleType>(env, dev, flags);
6735db71995Sopenharmony_ci    auto parent_type = get_parent_type<ParentType>(inst, dev);
6745db71995Sopenharmony_ci
6755db71995Sopenharmony_ci    if (has_flag(flags, TestConfig::add_layer_implementation) && has_flag(flags, TestConfig::add_layer_interception)) {
6765db71995Sopenharmony_ci        for (uint32_t i = 0; i < function_count / 10; i++) {
6775db71995Sopenharmony_ci            check_layer_custom_functions_no_interception(env.vulkan_functions, parent_type, dispatch_type, *layer_ptr,
6785db71995Sopenharmony_ci                                                         layer_implementation_functions_type{}, function_names, 5, i * 10);
6795db71995Sopenharmony_ci        }
6805db71995Sopenharmony_ci    } else if (has_flag(flags, TestConfig::add_layer_interception)) {
6815db71995Sopenharmony_ci        check_layer_custom_functions(env.vulkan_functions, parent_type, dispatch_type, *layer_ptr, layer_intercept_functions_type{},
6825db71995Sopenharmony_ci                                     function_names, function_count);
6835db71995Sopenharmony_ci
6845db71995Sopenharmony_ci    } else {
6855db71995Sopenharmony_ci        check_custom_functions(env.vulkan_functions, parent_type, dispatch_type, custom_functions_type{}, function_names,
6865db71995Sopenharmony_ci                               function_count);
6875db71995Sopenharmony_ci    }
6885db71995Sopenharmony_ci}
6895db71995Sopenharmony_ci
6905db71995Sopenharmony_ci// Device
6915db71995Sopenharmony_ci
6925db71995Sopenharmony_ciTEST(UnknownFunction, DeviceFromGDPA) { unknown_function_test_impl<VkDevice, VkDevice>({}); }
6935db71995Sopenharmony_ci
6945db71995Sopenharmony_ciTEST(UnknownFunction, DeviceFromGDPAWithLayerImplementation) {
6955db71995Sopenharmony_ci    unknown_function_test_impl<VkDevice, VkDevice>({TestConfig::add_layer_implementation});
6965db71995Sopenharmony_ci}
6975db71995Sopenharmony_ci
6985db71995Sopenharmony_ciTEST(UnknownFunction, DeviceFromGDPAWithLayerInterception) {
6995db71995Sopenharmony_ci    unknown_function_test_impl<VkDevice, VkDevice>({TestConfig::add_layer_interception});
7005db71995Sopenharmony_ci}
7015db71995Sopenharmony_ci
7025db71995Sopenharmony_ciTEST(UnknownFunction, DeviceFromGDPAWithLayerInterceptionAndLayerImplementation) {
7035db71995Sopenharmony_ci    unknown_function_test_impl<VkDevice, VkDevice>({TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
7045db71995Sopenharmony_ci}
7055db71995Sopenharmony_ci
7065db71995Sopenharmony_ciTEST(UnknownFunction, DeviceFromGIPA) { unknown_function_test_impl<VkInstance, VkDevice>({}); }
7075db71995Sopenharmony_ci
7085db71995Sopenharmony_ciTEST(UnknownFunction, DeviceFromGIPAWithLayerImplementation) {
7095db71995Sopenharmony_ci    unknown_function_test_impl<VkInstance, VkDevice>({TestConfig::add_layer_implementation});
7105db71995Sopenharmony_ci}
7115db71995Sopenharmony_ci
7125db71995Sopenharmony_ciTEST(UnknownFunction, DeviceFromGIPAWithLayerInterception) {
7135db71995Sopenharmony_ci    unknown_function_test_impl<VkInstance, VkDevice>({TestConfig::add_layer_implementation});
7145db71995Sopenharmony_ci}
7155db71995Sopenharmony_ci
7165db71995Sopenharmony_ciTEST(UnknownFunction, DeviceFromGIPAWithLayerInterceptionAndLayerImplementation) {
7175db71995Sopenharmony_ci    unknown_function_test_impl<VkInstance, VkDevice>({TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
7185db71995Sopenharmony_ci}
7195db71995Sopenharmony_ci
7205db71995Sopenharmony_ci// Command buffers
7215db71995Sopenharmony_ci
7225db71995Sopenharmony_ciTEST(UnknownFunction, CommandBufferFromGDPA) { unknown_function_test_impl<VkDevice, VkCommandBuffer>({}); }
7235db71995Sopenharmony_ci
7245db71995Sopenharmony_ciTEST(UnknownFunction, CommandBufferFromGDPAWithLayerImplementation) {
7255db71995Sopenharmony_ci    unknown_function_test_impl<VkDevice, VkCommandBuffer>({TestConfig::add_layer_implementation});
7265db71995Sopenharmony_ci}
7275db71995Sopenharmony_ci
7285db71995Sopenharmony_ciTEST(UnknownFunction, CommandBufferFromGDPAWithLayerInterception) {
7295db71995Sopenharmony_ci    unknown_function_test_impl<VkDevice, VkCommandBuffer>({TestConfig::add_layer_interception});
7305db71995Sopenharmony_ci}
7315db71995Sopenharmony_ci
7325db71995Sopenharmony_ciTEST(UnknownFunction, CommandBufferFromGDPAWithLayerInterceptionAndLayerImplementation) {
7335db71995Sopenharmony_ci    unknown_function_test_impl<VkDevice, VkCommandBuffer>(
7345db71995Sopenharmony_ci        {TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
7355db71995Sopenharmony_ci}
7365db71995Sopenharmony_ci
7375db71995Sopenharmony_ciTEST(UnknownFunction, CommandBufferFromGIPA) { unknown_function_test_impl<VkInstance, VkCommandBuffer>({}); }
7385db71995Sopenharmony_ci
7395db71995Sopenharmony_ciTEST(UnknownFunction, CommandBufferFromGIPAWithLayerImplementation) {
7405db71995Sopenharmony_ci    unknown_function_test_impl<VkInstance, VkCommandBuffer>({TestConfig::add_layer_implementation});
7415db71995Sopenharmony_ci}
7425db71995Sopenharmony_ci
7435db71995Sopenharmony_ciTEST(UnknownFunction, CommandBufferFromGIPAWithLayerInterception) {
7445db71995Sopenharmony_ci    unknown_function_test_impl<VkInstance, VkCommandBuffer>({TestConfig::add_layer_implementation});
7455db71995Sopenharmony_ci}
7465db71995Sopenharmony_ci
7475db71995Sopenharmony_ciTEST(UnknownFunction, CommandBufferFromGIPAWithLayerInterceptionAndLayerImplementation) {
7485db71995Sopenharmony_ci    unknown_function_test_impl<VkInstance, VkCommandBuffer>(
7495db71995Sopenharmony_ci        {TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
7505db71995Sopenharmony_ci}
7515db71995Sopenharmony_ci
7525db71995Sopenharmony_ci// Queues
7535db71995Sopenharmony_ci
7545db71995Sopenharmony_ciTEST(UnknownFunction, QueueFromGDPA) { unknown_function_test_impl<VkDevice, VkQueue>({}); }
7555db71995Sopenharmony_ci
7565db71995Sopenharmony_ciTEST(UnknownFunction, QueueFromGDPAWithLayerImplementation) {
7575db71995Sopenharmony_ci    unknown_function_test_impl<VkDevice, VkQueue>({TestConfig::add_layer_implementation});
7585db71995Sopenharmony_ci}
7595db71995Sopenharmony_ci
7605db71995Sopenharmony_ciTEST(UnknownFunction, QueueFromGDPAWithLayerInterception) {
7615db71995Sopenharmony_ci    unknown_function_test_impl<VkDevice, VkQueue>({TestConfig::add_layer_interception});
7625db71995Sopenharmony_ci}
7635db71995Sopenharmony_ci
7645db71995Sopenharmony_ciTEST(UnknownFunction, QueueFromGDPAWithLayerInterceptionAndLayerImplementation) {
7655db71995Sopenharmony_ci    unknown_function_test_impl<VkDevice, VkQueue>({TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
7665db71995Sopenharmony_ci}
7675db71995Sopenharmony_ci
7685db71995Sopenharmony_ciTEST(UnknownFunction, QueueFromGIPA) { unknown_function_test_impl<VkInstance, VkQueue>({}); }
7695db71995Sopenharmony_ci
7705db71995Sopenharmony_ciTEST(UnknownFunction, QueueFromGIPAWithLayer) {
7715db71995Sopenharmony_ci    unknown_function_test_impl<VkInstance, VkQueue>({TestConfig::add_layer_implementation});
7725db71995Sopenharmony_ci}
7735db71995Sopenharmony_ci
7745db71995Sopenharmony_ciTEST(UnknownFunction, QueueFromGIPAWithLayerInterception) {
7755db71995Sopenharmony_ci    unknown_function_test_impl<VkInstance, VkQueue>({TestConfig::add_layer_implementation});
7765db71995Sopenharmony_ci}
7775db71995Sopenharmony_ci
7785db71995Sopenharmony_ciTEST(UnknownFunction, QueueFromGIPAWithLayerInterceptionAndLayerImplementation) {
7795db71995Sopenharmony_ci    unknown_function_test_impl<VkInstance, VkQueue>({TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
7805db71995Sopenharmony_ci}
7815db71995Sopenharmony_ci
7825db71995Sopenharmony_ci/*
7835db71995Sopenharmony_ci The purpose of LayerInterceptData is to provide a place to store data that is accessible inside the interception function.
7845db71995Sopenharmony_ci It works by being a templated type with static variables. Every unique type used creates a new template instantiation, with its own
7855db71995Sopenharmony_ci static variable storage. Thus interception functions that are templated correctly have per-template static data storage at their
7865db71995Sopenharmony_ci disposal, which is used to query the next function in the chain and call down.
7875db71995Sopenharmony_ci*/
7885db71995Sopenharmony_ci
7895db71995Sopenharmony_citemplate <typename UniqueType>
7905db71995Sopenharmony_cistruct LayerInterceptData {
7915db71995Sopenharmony_ci    static TestLayer* layer;
7925db71995Sopenharmony_ci    static const char* name;
7935db71995Sopenharmony_ci};
7945db71995Sopenharmony_citemplate <typename UniqueType>
7955db71995Sopenharmony_ciTestLayer* LayerInterceptData<UniqueType>::layer = nullptr;
7965db71995Sopenharmony_citemplate <typename UniqueType>
7975db71995Sopenharmony_ciconst char* LayerInterceptData<UniqueType>::name = nullptr;
7985db71995Sopenharmony_ci
7995db71995Sopenharmony_citemplate <typename DispatchableHandle>
8005db71995Sopenharmony_cistruct FunctionZero {
8015db71995Sopenharmony_ci    static VKAPI_ATTR uint32_t VKAPI_CALL implementation(DispatchableHandle, uint32_t a, uint32_t b) { return a + b; }
8025db71995Sopenharmony_ci
8035db71995Sopenharmony_ci    template <typename LayerType>
8045db71995Sopenharmony_ci    static VKAPI_ATTR uint32_t VKAPI_CALL intercept(DispatchableHandle handle, uint32_t a, uint32_t b) {
8055db71995Sopenharmony_ci        decltype(implementation)* func =
8065db71995Sopenharmony_ci            reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
8075db71995Sopenharmony_ci        if (func == nullptr) return 1337;
8085db71995Sopenharmony_ci        return func(handle, a + 3, b + 7);
8095db71995Sopenharmony_ci    }
8105db71995Sopenharmony_ci
8115db71995Sopenharmony_ci    template <typename ParentType>
8125db71995Sopenharmony_ci    static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
8135db71995Sopenharmony_ci                      uint32_t interception_count = 1) {
8145db71995Sopenharmony_ci        decltype(implementation)* returned_func = loader.load(parent, name);
8155db71995Sopenharmony_ci        ASSERT_NE(returned_func, nullptr);
8165db71995Sopenharmony_ci        EXPECT_EQ(returned_func(dispatch_type, 4, 9), (4 + 3 * interception_count) + (9 + 7 * interception_count));
8175db71995Sopenharmony_ci    }
8185db71995Sopenharmony_ci    template <typename ParentType>
8195db71995Sopenharmony_ci    static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
8205db71995Sopenharmony_ci                                        const char* name) {
8215db71995Sopenharmony_ci        decltype(implementation)* returned_func = loader.load(parent, name);
8225db71995Sopenharmony_ci        ASSERT_NE(returned_func, nullptr);
8235db71995Sopenharmony_ci        EXPECT_EQ(returned_func(dispatch_type, 5, 2), 1337U);
8245db71995Sopenharmony_ci    }
8255db71995Sopenharmony_ci};
8265db71995Sopenharmony_ci
8275db71995Sopenharmony_citemplate <typename DispatchableHandle>
8285db71995Sopenharmony_cistruct FunctionOne {
8295db71995Sopenharmony_ci    static VKAPI_ATTR uint32_t VKAPI_CALL implementation(DispatchableHandle, uint32_t a, uint32_t b, char c) { return a + b + c; }
8305db71995Sopenharmony_ci
8315db71995Sopenharmony_ci    template <typename LayerType>
8325db71995Sopenharmony_ci    static VKAPI_ATTR uint32_t VKAPI_CALL intercept(DispatchableHandle handle, uint32_t a, uint32_t b, char c) {
8335db71995Sopenharmony_ci        decltype(implementation)* func =
8345db71995Sopenharmony_ci            reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
8355db71995Sopenharmony_ci        if (func == nullptr) return 1337;
8365db71995Sopenharmony_ci        return func(handle, a + 2, b + 9, c + 1);
8375db71995Sopenharmony_ci    }
8385db71995Sopenharmony_ci
8395db71995Sopenharmony_ci    template <typename ParentType>
8405db71995Sopenharmony_ci    static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
8415db71995Sopenharmony_ci                      uint32_t interception_count = 1) {
8425db71995Sopenharmony_ci        decltype(implementation)* returned_func = loader.load(parent, name);
8435db71995Sopenharmony_ci        ASSERT_NE(returned_func, nullptr);
8445db71995Sopenharmony_ci        EXPECT_EQ(returned_func(dispatch_type, 12, 17, 'a'),
8455db71995Sopenharmony_ci                  (12 + 2 * interception_count) + (17 + 9 * interception_count) + ('a' + 1 * interception_count));
8465db71995Sopenharmony_ci    }
8475db71995Sopenharmony_ci    template <typename ParentType>
8485db71995Sopenharmony_ci    static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
8495db71995Sopenharmony_ci                                        const char* name) {
8505db71995Sopenharmony_ci        decltype(implementation)* returned_func = loader.load(parent, name);
8515db71995Sopenharmony_ci        ASSERT_NE(returned_func, nullptr);
8525db71995Sopenharmony_ci        EXPECT_EQ(returned_func(dispatch_type, 1, 516, 'c'), 1337U);
8535db71995Sopenharmony_ci    }
8545db71995Sopenharmony_ci};
8555db71995Sopenharmony_ci
8565db71995Sopenharmony_citemplate <typename DispatchableHandle>
8575db71995Sopenharmony_cistruct FunctionTwo {
8585db71995Sopenharmony_ci    static VKAPI_ATTR float VKAPI_CALL implementation(DispatchableHandle, int* ptr_a, int* ptr_b) {
8595db71995Sopenharmony_ci        return 0.123f + *ptr_a + *ptr_b;
8605db71995Sopenharmony_ci    }
8615db71995Sopenharmony_ci
8625db71995Sopenharmony_ci    template <typename LayerType>
8635db71995Sopenharmony_ci    static VKAPI_ATTR float VKAPI_CALL intercept(DispatchableHandle handle, int* ptr_a, int* ptr_b) {
8645db71995Sopenharmony_ci        decltype(implementation)* func =
8655db71995Sopenharmony_ci            reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
8665db71995Sopenharmony_ci        if (func == nullptr) return -1337.f;
8675db71995Sopenharmony_ci        *ptr_a += 2;
8685db71995Sopenharmony_ci        *ptr_b += 5;
8695db71995Sopenharmony_ci        return func(handle, ptr_a, ptr_b);
8705db71995Sopenharmony_ci    }
8715db71995Sopenharmony_ci
8725db71995Sopenharmony_ci    template <typename ParentType>
8735db71995Sopenharmony_ci    static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
8745db71995Sopenharmony_ci                      uint32_t interception_count = 1) {
8755db71995Sopenharmony_ci        decltype(implementation)* returned_func = loader.load(parent, name);
8765db71995Sopenharmony_ci        ASSERT_NE(returned_func, nullptr);
8775db71995Sopenharmony_ci        int x = 10, y = 3;
8785db71995Sopenharmony_ci        EXPECT_NEAR(returned_func(dispatch_type, &x, &y), 0.123f + (10 + 2 * interception_count) + (3 + 5 * interception_count),
8795db71995Sopenharmony_ci                    0.001);
8805db71995Sopenharmony_ci    }
8815db71995Sopenharmony_ci    template <typename ParentType>
8825db71995Sopenharmony_ci    static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
8835db71995Sopenharmony_ci                                        const char* name) {
8845db71995Sopenharmony_ci        decltype(implementation)* returned_func = loader.load(parent, name);
8855db71995Sopenharmony_ci        ASSERT_NE(returned_func, nullptr);
8865db71995Sopenharmony_ci        int x = 10, y = 0;
8875db71995Sopenharmony_ci        EXPECT_NEAR(returned_func(dispatch_type, &x, &y), -1337.f, 0.001);
8885db71995Sopenharmony_ci    }
8895db71995Sopenharmony_ci};
8905db71995Sopenharmony_ci
8915db71995Sopenharmony_citemplate <typename DispatchableHandle>
8925db71995Sopenharmony_cistruct FunctionThree {
8935db71995Sopenharmony_ci    static VKAPI_ATTR float VKAPI_CALL implementation(DispatchableHandle, int* ptr_a, float* ptr_b, uint32_t c) {
8945db71995Sopenharmony_ci        return 0.456f + *ptr_a + *ptr_b + c;
8955db71995Sopenharmony_ci    }
8965db71995Sopenharmony_ci
8975db71995Sopenharmony_ci    template <typename LayerType>
8985db71995Sopenharmony_ci    static VKAPI_ATTR float VKAPI_CALL intercept(DispatchableHandle handle, int* ptr_a, float* ptr_b, uint32_t c) {
8995db71995Sopenharmony_ci        decltype(implementation)* func =
9005db71995Sopenharmony_ci            reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
9015db71995Sopenharmony_ci        if (func == nullptr) return -1837.f;
9025db71995Sopenharmony_ci        *ptr_a += 55;
9035db71995Sopenharmony_ci        *ptr_b += 5.98f;
9045db71995Sopenharmony_ci        return func(handle, ptr_a, ptr_b, c + 100);
9055db71995Sopenharmony_ci    }
9065db71995Sopenharmony_ci
9075db71995Sopenharmony_ci    template <typename ParentType>
9085db71995Sopenharmony_ci    static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
9095db71995Sopenharmony_ci                      uint32_t interception_count = 1) {
9105db71995Sopenharmony_ci        decltype(implementation)* returned_func = loader.load(parent, name);
9115db71995Sopenharmony_ci        ASSERT_NE(returned_func, nullptr);
9125db71995Sopenharmony_ci        int x = 96;
9135db71995Sopenharmony_ci        float y = 7;
9145db71995Sopenharmony_ci        EXPECT_NEAR(returned_func(dispatch_type, &x, &y, 30),
9155db71995Sopenharmony_ci                    0.456f + (96 + 55 * interception_count) + (7 + 5.98f * interception_count) + (30 + 100 * interception_count),
9165db71995Sopenharmony_ci                    0.001);
9175db71995Sopenharmony_ci    }
9185db71995Sopenharmony_ci    template <typename ParentType>
9195db71995Sopenharmony_ci    static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
9205db71995Sopenharmony_ci                                        const char* name) {
9215db71995Sopenharmony_ci        decltype(implementation)* returned_func = loader.load(parent, name);
9225db71995Sopenharmony_ci        ASSERT_NE(returned_func, nullptr);
9235db71995Sopenharmony_ci        int x = 10;
9245db71995Sopenharmony_ci        float y = 0;
9255db71995Sopenharmony_ci        EXPECT_NEAR(returned_func(dispatch_type, &x, &y, 40), -1837.f, 0.001);
9265db71995Sopenharmony_ci    }
9275db71995Sopenharmony_ci};
9285db71995Sopenharmony_ci
9295db71995Sopenharmony_citemplate <typename DispatchableHandle>
9305db71995Sopenharmony_cistruct FunctionFour {
9315db71995Sopenharmony_ci    static VKAPI_ATTR VkResult VKAPI_CALL implementation(DispatchableHandle, VkPhysicalDeviceLimits* limits, uint32_t* count,
9325db71995Sopenharmony_ci                                                         VkExtensionProperties* props) {
9335db71995Sopenharmony_ci        limits->nonCoherentAtomSize = 0x0000ABCD0000FEDCU;
9345db71995Sopenharmony_ci        if (props == nullptr) {
9355db71995Sopenharmony_ci            *count = 5;
9365db71995Sopenharmony_ci            return VK_INCOMPLETE;
9375db71995Sopenharmony_ci        } else {
9385db71995Sopenharmony_ci            for (uint32_t i = 0; i < *count; i++) {
9395db71995Sopenharmony_ci                props[i].specVersion = i;
9405db71995Sopenharmony_ci            }
9415db71995Sopenharmony_ci            return VK_SUCCESS;
9425db71995Sopenharmony_ci        }
9435db71995Sopenharmony_ci    }
9445db71995Sopenharmony_ci
9455db71995Sopenharmony_ci    template <typename LayerType>
9465db71995Sopenharmony_ci    static VKAPI_ATTR VkResult VKAPI_CALL intercept(DispatchableHandle handle, VkPhysicalDeviceLimits* limits, uint32_t* count,
9475db71995Sopenharmony_ci                                                    VkExtensionProperties* props) {
9485db71995Sopenharmony_ci        decltype(implementation)* func =
9495db71995Sopenharmony_ci            reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
9505db71995Sopenharmony_ci        if (func == nullptr) return VK_ERROR_DEVICE_LOST;
9515db71995Sopenharmony_ci        VkResult res = func(handle, limits, count, props);
9525db71995Sopenharmony_ci        if (props) {
9535db71995Sopenharmony_ci            for (uint32_t i = 5; i < *count; i++) {
9545db71995Sopenharmony_ci                props[i].specVersion = 1234 + i * 2;
9555db71995Sopenharmony_ci            }
9565db71995Sopenharmony_ci        } else if (count) {
9575db71995Sopenharmony_ci            *count += 1;
9585db71995Sopenharmony_ci        }
9595db71995Sopenharmony_ci        return res;
9605db71995Sopenharmony_ci    }
9615db71995Sopenharmony_ci
9625db71995Sopenharmony_ci    template <typename ParentType>
9635db71995Sopenharmony_ci    static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
9645db71995Sopenharmony_ci                      uint32_t interception_count = 1) {
9655db71995Sopenharmony_ci        decltype(implementation)* returned_func = loader.load(parent, name);
9665db71995Sopenharmony_ci        ASSERT_NE(returned_func, nullptr);
9675db71995Sopenharmony_ci        VkPhysicalDeviceLimits limits{};
9685db71995Sopenharmony_ci        uint32_t count = 0;
9695db71995Sopenharmony_ci        EXPECT_EQ(returned_func(dispatch_type, &limits, &count, nullptr), VK_INCOMPLETE);
9705db71995Sopenharmony_ci        EXPECT_EQ(count, 5 + interception_count);
9715db71995Sopenharmony_ci        std::vector<VkExtensionProperties> props(count, VkExtensionProperties{});
9725db71995Sopenharmony_ci        EXPECT_EQ(returned_func(dispatch_type, &limits, &count, props.data()), VK_SUCCESS);
9735db71995Sopenharmony_ci        for (uint32_t i = 0; i < 5; i++) {
9745db71995Sopenharmony_ci            EXPECT_EQ(props.at(i).specVersion, i);
9755db71995Sopenharmony_ci        }
9765db71995Sopenharmony_ci        for (uint32_t i = 5; i < interception_count; i++) {
9775db71995Sopenharmony_ci            EXPECT_EQ(props.at(i).specVersion, 1234 + i * 2);  // interception should do this
9785db71995Sopenharmony_ci        }
9795db71995Sopenharmony_ci    }
9805db71995Sopenharmony_ci    template <typename ParentType>
9815db71995Sopenharmony_ci    static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
9825db71995Sopenharmony_ci                                        const char* name) {
9835db71995Sopenharmony_ci        decltype(implementation)* returned_func = loader.load(parent, name);
9845db71995Sopenharmony_ci        ASSERT_NE(returned_func, nullptr);
9855db71995Sopenharmony_ci        VkPhysicalDeviceLimits limits{};
9865db71995Sopenharmony_ci        EXPECT_EQ(returned_func(dispatch_type, &limits, nullptr, nullptr), VK_ERROR_DEVICE_LOST);
9875db71995Sopenharmony_ci    }
9885db71995Sopenharmony_ci};
9895db71995Sopenharmony_ci
9905db71995Sopenharmony_cistruct UnknownFunction {
9915db71995Sopenharmony_ci    std::string name;
9925db71995Sopenharmony_ci
9935db71995Sopenharmony_ci    bool has_implementation = false;
9945db71995Sopenharmony_ci    std::vector<uint32_t> interception_stack;
9955db71995Sopenharmony_ci
9965db71995Sopenharmony_ci    UnknownFunction() = default;
9975db71995Sopenharmony_ci    UnknownFunction(std::string name) : name(name) {}
9985db71995Sopenharmony_ci
9995db71995Sopenharmony_ci    template <typename FunctionType, typename ParentType, typename DispatchableHandle>
10005db71995Sopenharmony_ci    void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type) {
10015db71995Sopenharmony_ci        if (has_implementation) {
10025db71995Sopenharmony_ci            // Find how many layers intercept this function, stop if any layer 'implements' the function, thus doesn't return
10035db71995Sopenharmony_ci            uint32_t intercept_count = 0;
10045db71995Sopenharmony_ci            for (auto const& elem : interception_stack) {
10055db71995Sopenharmony_ci                if (elem == 1) break;
10065db71995Sopenharmony_ci                intercept_count++;
10075db71995Sopenharmony_ci            }
10085db71995Sopenharmony_ci            FunctionType::Function::check(loader, parent, dispatch_type, name.c_str(), intercept_count);
10095db71995Sopenharmony_ci        } else {
10105db71995Sopenharmony_ci            FunctionType::Function::check_no_implementation(loader, parent, dispatch_type, name.c_str());
10115db71995Sopenharmony_ci        }
10125db71995Sopenharmony_ci    }
10135db71995Sopenharmony_ci
10145db71995Sopenharmony_ci    void push_layer_implementation() { interception_stack.push_back(1); }
10155db71995Sopenharmony_ci    void push_layer_interception() { interception_stack.push_back(0); }
10165db71995Sopenharmony_ci};
10175db71995Sopenharmony_ci
10185db71995Sopenharmony_ci// For VkDevice, VkCommandBuffer, & VkQueue
10195db71995Sopenharmony_citemplate <typename FunctionType, typename DispatchableHandle>
10205db71995Sopenharmony_cistruct UnknownFunctionInfo {
10215db71995Sopenharmony_ci    using Function = FunctionType;
10225db71995Sopenharmony_ci
10235db71995Sopenharmony_ci    static void add_to_driver(UnknownFunction& func, PhysicalDevice& physical_device) {
10245db71995Sopenharmony_ci        physical_device.add_device_function({func.name.c_str(), to_vkVoidFunction(Function::implementation)});
10255db71995Sopenharmony_ci        func.has_implementation = true;
10265db71995Sopenharmony_ci    }
10275db71995Sopenharmony_ci
10285db71995Sopenharmony_ci    template <typename LayerStruct>
10295db71995Sopenharmony_ci    static void add_to_layer(UnknownFunction& func, TestLayer& layer, LayerStruct) {
10305db71995Sopenharmony_ci        LayerInterceptData<LayerStruct>::layer = &layer;
10315db71995Sopenharmony_ci        LayerInterceptData<LayerStruct>::name = func.name.c_str();
10325db71995Sopenharmony_ci        layer.add_custom_device_interception_function(
10335db71995Sopenharmony_ci            func.name, to_vkVoidFunction(&Function::template intercept<LayerInterceptData<LayerStruct>>));
10345db71995Sopenharmony_ci        func.push_layer_interception();
10355db71995Sopenharmony_ci    }
10365db71995Sopenharmony_ci
10375db71995Sopenharmony_ci    static void add_implementation_to_layer(UnknownFunction& func, TestLayer& layer) {
10385db71995Sopenharmony_ci        layer.add_custom_device_implementation_function({func.name.c_str(), to_vkVoidFunction(Function::implementation)});
10395db71995Sopenharmony_ci        func.has_implementation = true;
10405db71995Sopenharmony_ci        func.push_layer_implementation();
10415db71995Sopenharmony_ci    }
10425db71995Sopenharmony_ci};
10435db71995Sopenharmony_ci
10445db71995Sopenharmony_ci// Specialization for VkPhysicalDevice
10455db71995Sopenharmony_ci
10465db71995Sopenharmony_citemplate <typename FunctionType>
10475db71995Sopenharmony_cistruct UnknownFunctionInfo<FunctionType, VkPhysicalDevice> {
10485db71995Sopenharmony_ci    using Function = FunctionType;
10495db71995Sopenharmony_ci
10505db71995Sopenharmony_ci    static void add_to_driver(UnknownFunction& func, PhysicalDevice& physical_device) {
10515db71995Sopenharmony_ci        physical_device.add_custom_physical_device_function({func.name.c_str(), to_vkVoidFunction(Function::implementation)});
10525db71995Sopenharmony_ci        func.has_implementation = true;
10535db71995Sopenharmony_ci    }
10545db71995Sopenharmony_ci
10555db71995Sopenharmony_ci    template <typename LayerStruct>
10565db71995Sopenharmony_ci    static void add_to_layer(UnknownFunction& func, TestLayer& layer, LayerStruct) {
10575db71995Sopenharmony_ci        LayerInterceptData<LayerStruct>::layer = &layer;
10585db71995Sopenharmony_ci        LayerInterceptData<LayerStruct>::name = func.name.c_str();
10595db71995Sopenharmony_ci        layer.add_custom_physical_device_intercept_function(
10605db71995Sopenharmony_ci            func.name, to_vkVoidFunction(&Function::template intercept<LayerInterceptData<LayerStruct>>));
10615db71995Sopenharmony_ci        func.push_layer_interception();
10625db71995Sopenharmony_ci    }
10635db71995Sopenharmony_ci
10645db71995Sopenharmony_ci    static void add_implementation_to_layer(UnknownFunction& func, TestLayer& layer) {
10655db71995Sopenharmony_ci        layer.add_custom_physical_device_implementation_function({func.name.c_str(), to_vkVoidFunction(Function::implementation)});
10665db71995Sopenharmony_ci        func.has_implementation = true;
10675db71995Sopenharmony_ci        func.push_layer_implementation();
10685db71995Sopenharmony_ci    }
10695db71995Sopenharmony_ci};
10705db71995Sopenharmony_ci
10715db71995Sopenharmony_cistruct Functions {
10725db71995Sopenharmony_ci    template <template <typename> class Function>
10735db71995Sopenharmony_ci    struct HelperTypedef {
10745db71995Sopenharmony_ci        using physical_device = UnknownFunctionInfo<Function<VkPhysicalDevice>, VkPhysicalDevice>;
10755db71995Sopenharmony_ci        using device = UnknownFunctionInfo<Function<VkDevice>, VkDevice>;
10765db71995Sopenharmony_ci        using command_buffer = UnknownFunctionInfo<Function<VkCommandBuffer>, VkCommandBuffer>;
10775db71995Sopenharmony_ci        using queue = UnknownFunctionInfo<Function<VkQueue>, VkQueue>;
10785db71995Sopenharmony_ci    };
10795db71995Sopenharmony_ci
10805db71995Sopenharmony_ci    using zero = HelperTypedef<FunctionZero>;
10815db71995Sopenharmony_ci    using one = HelperTypedef<FunctionOne>;
10825db71995Sopenharmony_ci    using two = HelperTypedef<FunctionTwo>;
10835db71995Sopenharmony_ci    using three = HelperTypedef<FunctionThree>;
10845db71995Sopenharmony_ci    using four = HelperTypedef<FunctionFour>;
10855db71995Sopenharmony_ci};
10865db71995Sopenharmony_ci
10875db71995Sopenharmony_citemplate <size_t I>
10885db71995Sopenharmony_cistruct D {};
10895db71995Sopenharmony_ci
10905db71995Sopenharmony_ciTEST(UnknownFunction, PhysicalDeviceFunctionTwoLayerInterception) {
10915db71995Sopenharmony_ci    FrameworkEnvironment env{};
10925db71995Sopenharmony_ci    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
10935db71995Sopenharmony_ci    PhysicalDevice& pd = driver.physical_devices.back();
10945db71995Sopenharmony_ci
10955db71995Sopenharmony_ci    UnknownFunction f{"vkFunc1"};
10965db71995Sopenharmony_ci    Functions::three::physical_device::add_to_driver(f, pd);
10975db71995Sopenharmony_ci
10985db71995Sopenharmony_ci    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
10995db71995Sopenharmony_ci                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
11005db71995Sopenharmony_ci                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
11015db71995Sopenharmony_ci                                                         .set_disable_environment("DISABLE_ME")),
11025db71995Sopenharmony_ci                           "implicit_layer_unknown_function_intercept.json");
11035db71995Sopenharmony_ci    auto& layer0 = env.get_test_layer(0);
11045db71995Sopenharmony_ci    Functions::three::physical_device::add_to_layer(f, layer0, D<0>{});
11055db71995Sopenharmony_ci
11065db71995Sopenharmony_ci    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
11075db71995Sopenharmony_ci                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept2")
11085db71995Sopenharmony_ci                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
11095db71995Sopenharmony_ci                                                         .set_disable_environment("DISABLE_ME")),
11105db71995Sopenharmony_ci                           "implicit_layer_unknown_function_intercept2.json");
11115db71995Sopenharmony_ci    auto& layer1 = env.get_test_layer(1);
11125db71995Sopenharmony_ci
11135db71995Sopenharmony_ci    Functions::three::physical_device::add_to_layer(f, layer1, D<1>{});
11145db71995Sopenharmony_ci
11155db71995Sopenharmony_ci    InstWrapper inst{env.vulkan_functions};
11165db71995Sopenharmony_ci    inst.CheckCreate();
11175db71995Sopenharmony_ci
11185db71995Sopenharmony_ci    VkPhysicalDevice phys_dev = inst.GetPhysDev();
11195db71995Sopenharmony_ci
11205db71995Sopenharmony_ci    f.check<Functions::three::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
11215db71995Sopenharmony_ci}
11225db71995Sopenharmony_ci
11235db71995Sopenharmony_ciTEST(UnknownFunction, ManyCombinations) {
11245db71995Sopenharmony_ci    FrameworkEnvironment env{};
11255db71995Sopenharmony_ci    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
11265db71995Sopenharmony_ci    PhysicalDevice& physical_device = driver.physical_devices.back();
11275db71995Sopenharmony_ci    std::vector<UnknownFunction> unknown_funcs;
11285db71995Sopenharmony_ci
11295db71995Sopenharmony_ci    unknown_funcs.emplace_back("vkZero_uint32_uint32_0");
11305db71995Sopenharmony_ci    unknown_funcs.emplace_back("vkOne_uint32_uint32_char_1");
11315db71995Sopenharmony_ci    unknown_funcs.emplace_back("vkTwo_ptr_int_ptr_int_2");
11325db71995Sopenharmony_ci    unknown_funcs.emplace_back("vkThree_ptr_int_ptr_float_uint_3");
11335db71995Sopenharmony_ci    unknown_funcs.emplace_back("vkFour_PD_limits_ptr_uint_ptr_ExtProps_4");
11345db71995Sopenharmony_ci    unknown_funcs.emplace_back("vkZero_uint32_uint32_5");
11355db71995Sopenharmony_ci    unknown_funcs.emplace_back("vkOne_uint32_uint32_char_6");
11365db71995Sopenharmony_ci    unknown_funcs.emplace_back("vkTwo_ptr_int_ptr_int_7");
11375db71995Sopenharmony_ci    unknown_funcs.emplace_back("vkThree_ptr_int_ptr_float_uint_8");
11385db71995Sopenharmony_ci    unknown_funcs.emplace_back("vkFour_PD_limits_ptr_uint_ptr_ExtProps_9");
11395db71995Sopenharmony_ci    unknown_funcs.emplace_back("vkZero_uint32_uint32_10");
11405db71995Sopenharmony_ci    unknown_funcs.emplace_back("vkOne_uint32_uint32_char_11");
11415db71995Sopenharmony_ci    unknown_funcs.emplace_back("vkTwo_ptr_int_ptr_int_12");
11425db71995Sopenharmony_ci
11435db71995Sopenharmony_ci    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
11445db71995Sopenharmony_ci                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_0")
11455db71995Sopenharmony_ci                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
11465db71995Sopenharmony_ci                                                         .set_disable_environment("DISABLE_ME")
11475db71995Sopenharmony_ci                                                         .add_device_extension(ManifestLayer::LayerDescription::Extension{
11485db71995Sopenharmony_ci                                                             "VK_EXT_for_the_laughs", 0, {"vkOne_uint32_uint32_char_11"}})),
11495db71995Sopenharmony_ci                           "implicit_layer_unknown_function_intercept_0.json");
11505db71995Sopenharmony_ci    auto& layer_0 = env.get_test_layer(0);
11515db71995Sopenharmony_ci    layer_0.set_use_gipa_GetPhysicalDeviceProcAddr(true);
11525db71995Sopenharmony_ci    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
11535db71995Sopenharmony_ci                                                         .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_1")
11545db71995Sopenharmony_ci                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
11555db71995Sopenharmony_ci                                                         .set_disable_environment("DISABLE_ME")),
11565db71995Sopenharmony_ci                           "implicit_layer_unknown_function_intercept_1.json");
11575db71995Sopenharmony_ci    auto& layer_1 = env.get_test_layer(1);
11585db71995Sopenharmony_ci    layer_1.set_use_gipa_GetPhysicalDeviceProcAddr(false);
11595db71995Sopenharmony_ci
11605db71995Sopenharmony_ci    // Physical Device functions
11615db71995Sopenharmony_ci    Functions::zero::physical_device::add_to_driver(unknown_funcs.at(0), physical_device);
11625db71995Sopenharmony_ci
11635db71995Sopenharmony_ci    Functions::one::physical_device::add_to_driver(unknown_funcs.at(1), physical_device);
11645db71995Sopenharmony_ci    Functions::one::physical_device::add_to_layer(unknown_funcs.at(1), layer_0, D<0>{});
11655db71995Sopenharmony_ci
11665db71995Sopenharmony_ci    Functions::two::physical_device::add_to_driver(unknown_funcs.at(2), physical_device);
11675db71995Sopenharmony_ci    Functions::two::physical_device::add_to_layer(unknown_funcs.at(2), layer_1, D<1>{});
11685db71995Sopenharmony_ci
11695db71995Sopenharmony_ci    Functions::three::physical_device::add_to_driver(unknown_funcs.at(3), physical_device);
11705db71995Sopenharmony_ci    Functions::three::physical_device::add_to_layer(unknown_funcs.at(3), layer_0, D<2>{});
11715db71995Sopenharmony_ci    Functions::three::physical_device::add_to_layer(unknown_funcs.at(3), layer_1, D<3>{});
11725db71995Sopenharmony_ci
11735db71995Sopenharmony_ci    Functions::four::physical_device::add_implementation_to_layer(unknown_funcs.at(4), layer_0);
11745db71995Sopenharmony_ci    Functions::four::physical_device::add_to_layer(unknown_funcs.at(4), layer_1, D<4>{});
11755db71995Sopenharmony_ci
11765db71995Sopenharmony_ci    Functions::zero::physical_device::add_to_layer(unknown_funcs.at(5), layer_0, D<5>{});
11775db71995Sopenharmony_ci    Functions::zero::physical_device::add_implementation_to_layer(unknown_funcs.at(5), layer_1);
11785db71995Sopenharmony_ci
11795db71995Sopenharmony_ci    Functions::two::physical_device::add_to_driver(unknown_funcs.at(12), physical_device);
11805db71995Sopenharmony_ci    Functions::zero::physical_device::add_to_layer(unknown_funcs.at(12), layer_0, D<12>{});
11815db71995Sopenharmony_ci    Functions::zero::physical_device::add_implementation_to_layer(unknown_funcs.at(12), layer_1);
11825db71995Sopenharmony_ci
11835db71995Sopenharmony_ci    // Device functions
11845db71995Sopenharmony_ci    Functions::one::device::add_to_driver(unknown_funcs.at(6), physical_device);
11855db71995Sopenharmony_ci
11865db71995Sopenharmony_ci    Functions::two::device::add_to_driver(unknown_funcs.at(7), physical_device);
11875db71995Sopenharmony_ci    Functions::two::device::add_to_layer(unknown_funcs.at(7), layer_0, D<6>{});
11885db71995Sopenharmony_ci
11895db71995Sopenharmony_ci    Functions::three::device::add_to_driver(unknown_funcs.at(8), physical_device);
11905db71995Sopenharmony_ci    Functions::three::device::add_to_layer(unknown_funcs.at(8), layer_1, D<7>{});
11915db71995Sopenharmony_ci
11925db71995Sopenharmony_ci    Functions::four::device::add_to_driver(unknown_funcs.at(9), physical_device);
11935db71995Sopenharmony_ci    Functions::four::device::add_to_layer(unknown_funcs.at(9), layer_0, D<8>{});
11945db71995Sopenharmony_ci    Functions::four::device::add_to_layer(unknown_funcs.at(9), layer_1, D<9>{});
11955db71995Sopenharmony_ci
11965db71995Sopenharmony_ci    Functions::zero::device::add_implementation_to_layer(unknown_funcs.at(10), layer_0);
11975db71995Sopenharmony_ci    Functions::zero::device::add_to_layer(unknown_funcs.at(10), layer_1, D<10>{});
11985db71995Sopenharmony_ci
11995db71995Sopenharmony_ci    Functions::one::device::add_to_layer(unknown_funcs.at(11), layer_0, D<11>{});
12005db71995Sopenharmony_ci    Functions::one::device::add_implementation_to_layer(unknown_funcs.at(11), layer_1);
12015db71995Sopenharmony_ci
12025db71995Sopenharmony_ci    {
12035db71995Sopenharmony_ci        InstWrapper inst{env.vulkan_functions};
12045db71995Sopenharmony_ci        inst.CheckCreate();
12055db71995Sopenharmony_ci
12065db71995Sopenharmony_ci        VkPhysicalDevice phys_dev = inst.GetPhysDev();
12075db71995Sopenharmony_ci        DeviceWrapper dev{inst};
12085db71995Sopenharmony_ci        dev.CheckCreate(phys_dev);
12095db71995Sopenharmony_ci
12105db71995Sopenharmony_ci        unknown_funcs.at(0).check<Functions::zero::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
12115db71995Sopenharmony_ci        unknown_funcs.at(1).check<Functions::one::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
12125db71995Sopenharmony_ci        unknown_funcs.at(2).check<Functions::two::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
12135db71995Sopenharmony_ci        unknown_funcs.at(3).check<Functions::three::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
12145db71995Sopenharmony_ci        unknown_funcs.at(4).check<Functions::four::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
12155db71995Sopenharmony_ci        unknown_funcs.at(5).check<Functions::zero::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
12165db71995Sopenharmony_ci
12175db71995Sopenharmony_ci        // Check that GIPA works for device functions
12185db71995Sopenharmony_ci        unknown_funcs.at(6).check<Functions::one::device>(env.vulkan_functions, inst.inst, dev.dev);
12195db71995Sopenharmony_ci        unknown_funcs.at(7).check<Functions::two::device>(env.vulkan_functions, inst.inst, dev.dev);
12205db71995Sopenharmony_ci        unknown_funcs.at(8).check<Functions::three::device>(env.vulkan_functions, inst.inst, dev.dev);
12215db71995Sopenharmony_ci        unknown_funcs.at(9).check<Functions::four::device>(env.vulkan_functions, inst.inst, dev.dev);
12225db71995Sopenharmony_ci        unknown_funcs.at(10).check<Functions::zero::device>(env.vulkan_functions, inst.inst, dev.dev);
12235db71995Sopenharmony_ci        unknown_funcs.at(11).check<Functions::one::device>(env.vulkan_functions, inst.inst, dev.dev);
12245db71995Sopenharmony_ci
12255db71995Sopenharmony_ci        // Check that GDPA works for device functions
12265db71995Sopenharmony_ci        unknown_funcs.at(6).check<Functions::one::device>(env.vulkan_functions, dev.dev, dev.dev);
12275db71995Sopenharmony_ci        unknown_funcs.at(7).check<Functions::two::device>(env.vulkan_functions, dev.dev, dev.dev);
12285db71995Sopenharmony_ci        unknown_funcs.at(8).check<Functions::three::device>(env.vulkan_functions, dev.dev, dev.dev);
12295db71995Sopenharmony_ci        unknown_funcs.at(9).check<Functions::four::device>(env.vulkan_functions, dev.dev, dev.dev);
12305db71995Sopenharmony_ci        unknown_funcs.at(10).check<Functions::zero::device>(env.vulkan_functions, dev.dev, dev.dev);
12315db71995Sopenharmony_ci        unknown_funcs.at(11).check<Functions::one::device>(env.vulkan_functions, dev.dev, dev.dev);
12325db71995Sopenharmony_ci    }
12335db71995Sopenharmony_ci
12345db71995Sopenharmony_ci    {
12355db71995Sopenharmony_ci        InstWrapper inst{env.vulkan_functions};
12365db71995Sopenharmony_ci        inst.CheckCreate();
12375db71995Sopenharmony_ci
12385db71995Sopenharmony_ci        VkPhysicalDevice phys_dev = inst.GetPhysDev();
12395db71995Sopenharmony_ci        DeviceWrapper dev{inst};
12405db71995Sopenharmony_ci        dev.CheckCreate(phys_dev);
12415db71995Sopenharmony_ci        // Load device functions first, to make sure order of function loading is not important
12425db71995Sopenharmony_ci        // Check that GIPA works for device functions
12435db71995Sopenharmony_ci        unknown_funcs.at(6).check<Functions::one::device>(env.vulkan_functions, inst.inst, dev.dev);
12445db71995Sopenharmony_ci        unknown_funcs.at(7).check<Functions::two::device>(env.vulkan_functions, inst.inst, dev.dev);
12455db71995Sopenharmony_ci        unknown_funcs.at(8).check<Functions::three::device>(env.vulkan_functions, inst.inst, dev.dev);
12465db71995Sopenharmony_ci        unknown_funcs.at(9).check<Functions::four::device>(env.vulkan_functions, inst.inst, dev.dev);
12475db71995Sopenharmony_ci        unknown_funcs.at(10).check<Functions::zero::device>(env.vulkan_functions, inst.inst, dev.dev);
12485db71995Sopenharmony_ci        unknown_funcs.at(11).check<Functions::one::device>(env.vulkan_functions, inst.inst, dev.dev);
12495db71995Sopenharmony_ci
12505db71995Sopenharmony_ci        // Check that GDPA works for device functions
12515db71995Sopenharmony_ci        unknown_funcs.at(6).check<Functions::one::device>(env.vulkan_functions, dev.dev, dev.dev);
12525db71995Sopenharmony_ci        unknown_funcs.at(7).check<Functions::two::device>(env.vulkan_functions, dev.dev, dev.dev);
12535db71995Sopenharmony_ci        unknown_funcs.at(8).check<Functions::three::device>(env.vulkan_functions, dev.dev, dev.dev);
12545db71995Sopenharmony_ci        unknown_funcs.at(9).check<Functions::four::device>(env.vulkan_functions, dev.dev, dev.dev);
12555db71995Sopenharmony_ci        unknown_funcs.at(10).check<Functions::zero::device>(env.vulkan_functions, dev.dev, dev.dev);
12565db71995Sopenharmony_ci        unknown_funcs.at(11).check<Functions::one::device>(env.vulkan_functions, dev.dev, dev.dev);
12575db71995Sopenharmony_ci
12585db71995Sopenharmony_ci        unknown_funcs.at(0).check<Functions::zero::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
12595db71995Sopenharmony_ci        unknown_funcs.at(1).check<Functions::one::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
12605db71995Sopenharmony_ci        unknown_funcs.at(2).check<Functions::two::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
12615db71995Sopenharmony_ci        unknown_funcs.at(3).check<Functions::three::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
12625db71995Sopenharmony_ci        unknown_funcs.at(4).check<Functions::four::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
12635db71995Sopenharmony_ci        unknown_funcs.at(5).check<Functions::zero::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
12645db71995Sopenharmony_ci    }
12655db71995Sopenharmony_ci}
12665db71995Sopenharmony_ci
12675db71995Sopenharmony_ciTEST(UnknownFunction, PhysicalDeviceFunctionInLayer) {
12685db71995Sopenharmony_ci    FrameworkEnvironment env{};
12695db71995Sopenharmony_ci    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
12705db71995Sopenharmony_ci
12715db71995Sopenharmony_ci    env.add_implicit_layer(ManifestLayer{}
12725db71995Sopenharmony_ci                               .add_layer(ManifestLayer::LayerDescription{}
12735db71995Sopenharmony_ci                                              .set_name("VK_LAYER_implicit_layer_1")
12745db71995Sopenharmony_ci                                              .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_0)
12755db71995Sopenharmony_ci                                              .set_disable_environment("DISABLE_ME"))
12765db71995Sopenharmony_ci                               .set_file_format_version({1, 0, 0}),
12775db71995Sopenharmony_ci                           "implicit_layer_1.json");
12785db71995Sopenharmony_ci
12795db71995Sopenharmony_ci    UnknownFunction unknown_func{"vkPhysicalDeviceFunctionInLayer"};
12805db71995Sopenharmony_ci    const char* ext_name = "VK_EXT_not_funny";
12815db71995Sopenharmony_ci
12825db71995Sopenharmony_ci    const char* explicit_layer_unknown_function_implement = "VK_LAYER_implement_unknown_function";
12835db71995Sopenharmony_ci    env.add_explicit_layer(
12845db71995Sopenharmony_ci        ManifestLayer{}
12855db71995Sopenharmony_ci            .add_layer(ManifestLayer::LayerDescription{}
12865db71995Sopenharmony_ci                           .set_name(explicit_layer_unknown_function_implement)
12875db71995Sopenharmony_ci                           .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
12885db71995Sopenharmony_ci                           .add_instance_extension(ManifestLayer::LayerDescription::Extension{ext_name, 0, {unknown_func.name}}))
12895db71995Sopenharmony_ci            .set_file_format_version({1, 1, 0}),
12905db71995Sopenharmony_ci        "implement_unknown_function.json");
12915db71995Sopenharmony_ci    auto& layer0 = env.get_test_layer(1);
12925db71995Sopenharmony_ci
12935db71995Sopenharmony_ci    const char* explicit_layer_to_enable_1 = "VK_LAYER_explicit_layer_1";
12945db71995Sopenharmony_ci    env.add_explicit_layer(ManifestLayer{}
12955db71995Sopenharmony_ci                               .add_layer(ManifestLayer::LayerDescription{}
12965db71995Sopenharmony_ci                                              .set_name(explicit_layer_to_enable_1)
12975db71995Sopenharmony_ci                                              .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2))
12985db71995Sopenharmony_ci                               .set_file_format_version({1, 2, 0}),
12995db71995Sopenharmony_ci                           "explicit_layer_2.json");
13005db71995Sopenharmony_ci
13015db71995Sopenharmony_ci    Functions::four::physical_device::add_implementation_to_layer(unknown_func, layer0);
13025db71995Sopenharmony_ci
13035db71995Sopenharmony_ci    InstWrapper inst{env.vulkan_functions};
13045db71995Sopenharmony_ci    inst.create_info.add_layer(explicit_layer_to_enable_1);
13055db71995Sopenharmony_ci    inst.create_info.add_layer(explicit_layer_unknown_function_implement);
13065db71995Sopenharmony_ci    inst.CheckCreate();
13075db71995Sopenharmony_ci
13085db71995Sopenharmony_ci    VkPhysicalDevice phys_dev = inst.GetPhysDev();
13095db71995Sopenharmony_ci
13105db71995Sopenharmony_ci    unknown_func.check<Functions::four::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
13115db71995Sopenharmony_ci}
1312