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