1 /*
2  * Copyright (c) 2021 The Khronos Group Inc.
3  * Copyright (c) 2021 Valve Corporation
4  * Copyright (c) 2021 LunarG, Inc.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and/or associated documentation files (the "Materials"), to
8  * deal in the Materials without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Materials, and to permit persons to whom the Materials are
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice(s) and this permission notice shall be included in
14  * all copies or substantial portions of the Materials.
15  *
16  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19  *
20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
23  * USE OR OTHER DEALINGS IN THE MATERIALS.
24  *
25  * Author: Charles Giessen <charles@lunarg.com>
26  */
27 
28 #include "test_environment.h"
29 #include <functional>
30 #include <tuple>
31 
32 enum class TestConfig {
33     add_layer_implementation,
34     add_layer_interception,
35 };
36 
has_flag(std::vector<TestConfig> const& flags, TestConfig config)37 bool has_flag(std::vector<TestConfig> const& flags, TestConfig config) {
38     for (auto const& flag : flags)
39         if (flag == config) return true;
40     return false;
41 }
42 
43 /*
44  Creates a TestICD with a function unknown to the loader called vkNotRealFuncTEST. The TestICD, when
45  vk_icdGetPhysicalDeviceProcAddr is called, will return the custom_physical_device_function if the function name matches
46  vkNotRealFuncTEST. The test then calls the function to verify that the unknown physical device function dispatching is
47  working correctly.
48 */
49 template <typename DispatchableHandleType>
50 struct custom_functions {
func_zerocustom_functions51     static VKAPI_ATTR uint32_t VKAPI_CALL func_zero(DispatchableHandleType, uint32_t foo) { return foo; };
func_onecustom_functions52     static VKAPI_ATTR uint32_t VKAPI_CALL func_one(DispatchableHandleType, uint32_t foo, uint32_t bar) { return foo + bar; };
func_twocustom_functions53     static VKAPI_ATTR float VKAPI_CALL func_two(DispatchableHandleType, uint32_t foo, uint32_t bar, float baz) {
54         return baz + foo + bar;
55     };
func_threecustom_functions56     static VKAPI_ATTR int VKAPI_CALL func_three(DispatchableHandleType, int* ptr_a, int* ptr_b) { return *ptr_a + *ptr_b; };
func_fourcustom_functions57     static VKAPI_ATTR float VKAPI_CALL func_four(DispatchableHandleType, int* ptr_a, int* ptr_b, int foo, int bar, float k, float l,
58                                                  char a, char b, char c) {
59         return *ptr_a + *ptr_b + foo + bar + k + l + static_cast<int>(a) + static_cast<int>(b) + static_cast<int>(c);
60     };
61 };
62 
63 /*
64 Functions for testing of layer interception of unknown functions. Note the need to pass a pointer to the layer and the name
65 of the called function as a parameter, this is necessary to allow a generic layer implementation, as the layer must look up
66 the function pointer to use. A real layer would store the function pointer in a dedicated structure per-instance/device, but
67 since the TestLayer is a generic layer, there isn't a fixed list of functions that should be supported.
68 */
69 
find_custom_func(TestLayer* layer, const char* name)70 PFN_vkVoidFunction find_custom_func(TestLayer* layer, const char* name) {
71     if (layer->custom_dispatch_functions.count(name) > 0) {
72         return layer->custom_dispatch_functions.at(name);
73     }
74     return nullptr;
75 }
76 
77 template <typename DispatchableHandleType>
78 struct layer_intercept_functions {
func_zerolayer_intercept_functions79     static VKAPI_ATTR uint32_t VKAPI_CALL func_zero(DispatchableHandleType handle, TestLayer* layer, const char* name, uint32_t i) {
80         auto func = reinterpret_cast<decltype(&func_zero)>(find_custom_func(layer, name));
81         if (func == nullptr) return 1337;
82         return func(handle, layer, name, i + 3);
83     }
func_onelayer_intercept_functions84     static VKAPI_ATTR uint32_t VKAPI_CALL func_one(DispatchableHandleType handle, TestLayer* layer, const char* name, uint32_t i,
85                                                    float f) {
86         auto func = reinterpret_cast<decltype(&func_one)>(find_custom_func(layer, name));
87         if (func == nullptr) return 1337;
88         return func(handle, layer, name, i + 2, f + 1.f);
89     }
func_twolayer_intercept_functions90     static VKAPI_ATTR float VKAPI_CALL func_two(DispatchableHandleType handle, TestLayer* layer, const char* name, uint32_t foo,
91                                                 uint32_t bar, float baz) {
92         auto func = reinterpret_cast<decltype(&func_two)>(find_custom_func(layer, name));
93         if (func == nullptr) return -1337;
94         return func(handle, layer, name, foo + 1, bar + 2, baz * 2);
95     };
func_threelayer_intercept_functions96     static VKAPI_ATTR int VKAPI_CALL func_three(DispatchableHandleType handle, TestLayer* layer, const char* name, int* ptr_a,
97                                                 int* ptr_b) {
98         auto func = reinterpret_cast<decltype(&func_three)>(find_custom_func(layer, name));
99         if (func == nullptr) return -1337;
100         *ptr_a += 1;
101         *ptr_b -= 2;
102         return func(handle, layer, name, ptr_a, ptr_b);
103     };
func_fourlayer_intercept_functions104     static VKAPI_ATTR float VKAPI_CALL func_four(DispatchableHandleType handle, TestLayer* layer, const char* name, int* ptr_a,
105                                                  int* ptr_b, int foo, int bar, float k, float l, char, char, char) {
106         auto func = reinterpret_cast<decltype(&func_four)>(find_custom_func(layer, name));
107         if (func == nullptr) return -1337.f;
108         return func(handle, layer, name, ptr_a, ptr_b, foo + 4, bar + 5, k + 1, l + 2, 'd', 'e', 'f');
109     };
110 };
111 
112 template <typename DispatchableHandleType>
113 struct layer_implementation_functions {
func_zerolayer_implementation_functions114     static VKAPI_ATTR uint32_t VKAPI_CALL func_zero(DispatchableHandleType, TestLayer*, const char*, uint32_t i) { return i * 3; }
func_onelayer_implementation_functions115     static VKAPI_ATTR uint32_t VKAPI_CALL func_one(DispatchableHandleType, TestLayer*, const char*, uint32_t i, float f) {
116         return static_cast<int>(i * 3 + f * 10.f);
117     }
func_twolayer_implementation_functions118     static VKAPI_ATTR float VKAPI_CALL func_two(DispatchableHandleType, TestLayer*, const char*, uint32_t foo, uint32_t bar,
119                                                 float baz) {
120         return baz + foo + bar;
121     };
func_threelayer_implementation_functions122     static VKAPI_ATTR int VKAPI_CALL func_three(DispatchableHandleType, TestLayer*, const char*, int* ptr_a, int* ptr_b) {
123         return *ptr_a + *ptr_b;
124     };
func_fourlayer_implementation_functions125     static VKAPI_ATTR float VKAPI_CALL func_four(DispatchableHandleType, TestLayer*, const char*, int* ptr_a, int* ptr_b, int foo,
126                                                  int bar, float k, float l, char a, char b, char c) {
127         return *ptr_a + *ptr_b + foo + bar + k + l + static_cast<int>(a) + static_cast<int>(b) + static_cast<int>(c);
128     };
129 };
130 
131 // Add function_count strings to the func_names vector, starting at function_start place. Essentially a utility for filling
132 // up a list of names to use later
add_function_names(std::vector<std::string>& func_names, uint32_t function_count, uint32_t function_start = 0)133 void add_function_names(std::vector<std::string>& func_names, uint32_t function_count, uint32_t function_start = 0) {
134     for (uint32_t i = function_start; i < function_start + function_count;) {
135         func_names.push_back(std::string("vkNotIntRealFuncTEST_") + std::to_string(i++));
136         func_names.push_back(std::string("vkNotIntRealIntFuncTEST_") + std::to_string(i++));
137         func_names.push_back(std::string("vkIntNotIntRealFloatFuncTEST_") + std::to_string(i++));
138         func_names.push_back(std::string("vkNotRealFuncPointerPointerTEST_") + std::to_string(i++));
139         func_names.push_back(std::string("vkNotRealFuncTEST_pointer_pointer_int_int_float_float_char_char_char_") +
140                              std::to_string(i++));
141     }
142 }
143 
144 // Add data to the function_list, which could be a driver or a layer list of implementation functions.
145 template <typename FunctionStruct>
fill_implementation_functions(std::vector<VulkanFunction>& function_list, std::vector<std::string>& func_names, FunctionStruct const& funcs, uint32_t function_count, uint32_t function_start = 0)146 void fill_implementation_functions(std::vector<VulkanFunction>& function_list, std::vector<std::string>& func_names,
147                                    FunctionStruct const& funcs, uint32_t function_count, uint32_t function_start = 0) {
148     for (uint32_t i = function_start; i < function_start + function_count;) {
149         function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_zero)});
150         function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_one)});
151         function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_two)});
152         function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_three)});
153         function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_four)});
154     }
155 }
156 
157 // Add device interception functions to a layer. Need to call `add_custom_device_interception_function` since the layer has
158 // to setup a unordered_map for storing the next function in the chain, and key it based on the name
159 template <typename FunctionStruct>
fill_device_intercept_functions(TestLayer& layer, std::vector<std::string>& func_names, FunctionStruct const& funcs, uint32_t function_count, uint32_t function_start = 0)160 void fill_device_intercept_functions(TestLayer& layer, std::vector<std::string>& func_names, FunctionStruct const& funcs,
161                                      uint32_t function_count, uint32_t function_start = 0) {
162     for (uint32_t i = function_start; i < function_start + function_count;) {
163         layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_zero));
164         layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_one));
165         layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_two));
166         layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_three));
167         layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_four));
168     }
169 }
170 // Add physical device interception functions to a layer. Need to call `add_custom_device_interception_function` since the
171 // layer has to setup a unordered_map for storing the next function in the chain, and key it based on the name
172 template <typename FunctionStruct>
fill_phys_dev_intercept_functions(TestLayer& layer, std::vector<std::string>& func_names, FunctionStruct const& funcs, uint32_t function_count, uint32_t function_start = 0)173 void fill_phys_dev_intercept_functions(TestLayer& layer, std::vector<std::string>& func_names, FunctionStruct const& funcs,
174                                        uint32_t function_count, uint32_t function_start = 0) {
175     for (uint32_t i = function_start; i < function_start + function_count;) {
176         layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_zero));
177         layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_one));
178         layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_two));
179         layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_three));
180         layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_four));
181     }
182 }
183 
184 template <typename FunctionLoader, typename ParentType, typename DispatchableHandleType, typename FunctionStruct>
check_custom_functions(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle, FunctionStruct const&, std::vector<std::string>& func_names, uint32_t function_count, uint32_t function_start = 0)185 void check_custom_functions(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle, FunctionStruct const&,
186                             std::vector<std::string>& func_names, uint32_t function_count, uint32_t function_start = 0) {
187     for (uint32_t i = function_start; i < function_start + function_count;) {
188         decltype(FunctionStruct::func_zero)* returned_func_i = loader.load(parent, func_names.at(i++).c_str());
189         ASSERT_NE(returned_func_i, nullptr);
190         EXPECT_EQ(returned_func_i(handle, i * 10), i * 10);
191 
192         decltype(FunctionStruct::func_one)* returned_func_ii = loader.load(parent, func_names.at(i++).c_str());
193         ASSERT_NE(returned_func_ii, nullptr);
194         EXPECT_EQ(returned_func_ii(handle, i * 10, i * 5), i * 10 + i * 5);
195 
196         decltype(FunctionStruct::func_two)* returned_func_iif = loader.load(parent, func_names.at(i++).c_str());
197         ASSERT_NE(returned_func_iif, nullptr);
198         EXPECT_NEAR(returned_func_iif(handle, i * 10, i * 5, 0.1234f), i * 10 + i * 5 + 0.1234f, 0.001);
199 
200         int x = 5;
201         int y = -505;
202         decltype(FunctionStruct::func_three)* returned_func_pp = loader.load(parent, func_names.at(i++).c_str());
203         ASSERT_NE(returned_func_pp, nullptr);
204         EXPECT_EQ(returned_func_pp(handle, &x, &y), -500);
205 
206         x = 5;
207         y = -505;
208         decltype(FunctionStruct::func_four)* returned_func_ppiiffccc = loader.load(parent, func_names.at(i++).c_str());
209         ASSERT_NE(returned_func_ppiiffccc, nullptr);
210         EXPECT_NEAR(returned_func_ppiiffccc(handle, &x, &y, 200, 300, 0.123f, 1001.89f, 'a', 'b', 'c'),
211                     -500 + 200 + 300 + 0.123 + 1001.89 + 97 + 98 + 99, 0.001f);
212     }
213 }
214 
215 template <typename FunctionLoader, typename ParentType, typename DispatchableHandleType, typename FunctionStruct>
check_layer_custom_functions(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle, TestLayer& layer, FunctionStruct const&, std::vector<std::string>& func_names, uint32_t function_count, uint32_t function_start = 0)216 void check_layer_custom_functions(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle, TestLayer& layer,
217                                   FunctionStruct const&, std::vector<std::string>& func_names, uint32_t function_count,
218                                   uint32_t function_start = 0) {
219     for (uint32_t i = function_start; i < function_start + function_count;) {
220         decltype(FunctionStruct::func_zero)* returned_func_i = loader.load(parent, func_names.at(i).c_str());
221         ASSERT_NE(returned_func_i, nullptr);
222         EXPECT_EQ(returned_func_i(handle, &layer, func_names.at(i).c_str(), i), (i + 3) * 3);
223         i++;
224         decltype(FunctionStruct::func_one)* returned_func_if = loader.load(parent, func_names.at(i).c_str());
225         ASSERT_NE(returned_func_if, nullptr);
226         EXPECT_EQ(returned_func_if(handle, &layer, func_names.at(i).c_str(), i, i + 1.f), (i + 2) * 3 + (i + 2) * 10);
227         i++;
228 
229         decltype(FunctionStruct::func_two)* returned_func_iif = loader.load(parent, func_names.at(i).c_str());
230         ASSERT_NE(returned_func_iif, nullptr);
231         EXPECT_NEAR(returned_func_iif(handle, &layer, func_names.at(i).c_str(), i * 10, i * 5, 0.1234f),
232                     (i * 10 + 1) + (i * 5 + 2) + (0.1234f * 2.f), 0.001);
233         i++;
234 
235         int x = 5 + i;
236         int y = -505 - i;
237         decltype(FunctionStruct::func_three)* returned_func_pp = loader.load(parent, func_names.at(i).c_str());
238         ASSERT_NE(returned_func_pp, nullptr);
239         EXPECT_EQ(returned_func_pp(handle, &layer, func_names.at(i).c_str(), &x, &y),
240                   (5 + static_cast<int>(i) + 1) + (-505 - static_cast<int>(i) - 2));
241         i++;
242 
243         x = 5;
244         y = -505;
245         decltype(FunctionStruct::func_four)* returned_func_ppiiffccc = loader.load(parent, func_names.at(i).c_str());
246         ASSERT_NE(returned_func_ppiiffccc, nullptr);
247         EXPECT_NEAR(
248             returned_func_ppiiffccc(handle, &layer, func_names.at(i).c_str(), &x, &y, 200, 300, 0.123f, 1001.89f, 'a', 'b', 'c'),
249             -500 + (200 + 4) + (300 + 5) + (0.123 + 1) + (1001.89 + 2) + 100 + 101 + 102,
250             0.001f);  // layer changes abc to def
251         i++;
252     }
253 }
254 
255 template <typename FunctionLoader, typename ParentType, typename DispatchableHandleType, typename FunctionStruct>
check_layer_custom_functions_no_implementation(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle, TestLayer& layer, FunctionStruct const&, std::vector<std::string>& func_names, uint32_t function_count, uint32_t function_start = 0)256 void check_layer_custom_functions_no_implementation(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle,
257                                                     TestLayer& layer, FunctionStruct const&, std::vector<std::string>& func_names,
258                                                     uint32_t function_count, uint32_t function_start = 0) {
259     for (uint32_t i = function_start; i < function_start + function_count;) {
260         decltype(FunctionStruct::func_zero)* returned_func_i = loader.load(parent, func_names.at(i).c_str());
261         ASSERT_NE(returned_func_i, nullptr);
262         EXPECT_EQ(1337U, returned_func_i(handle, &layer, func_names.at(i).c_str(), i));
263         i++;
264         decltype(FunctionStruct::func_one)* returned_func_if = loader.load(parent, func_names.at(i).c_str());
265         ASSERT_NE(returned_func_if, nullptr);
266         EXPECT_EQ(1337U, returned_func_if(handle, &layer, func_names.at(i).c_str(), i, i + 1.f));
267         i++;
268 
269         decltype(FunctionStruct::func_two)* returned_func_iif = loader.load(parent, func_names.at(i).c_str());
270         ASSERT_NE(returned_func_iif, nullptr);
271         EXPECT_NEAR(-1337.0, returned_func_iif(handle, &layer, func_names.at(i).c_str(), i * 10, i * 5, 0.1234f), 0.001);
272         i++;
273 
274         int x = 5 + i;
275         int y = -505 - i;
276         decltype(FunctionStruct::func_three)* returned_func_pp = loader.load(parent, func_names.at(i).c_str());
277         ASSERT_NE(returned_func_pp, nullptr);
278         EXPECT_EQ(-1337, returned_func_pp(handle, &layer, func_names.at(i).c_str(), &x, &y));
279         i++;
280 
281         x = 5;
282         y = -505;
283         decltype(FunctionStruct::func_four)* returned_func_ppiiffccc = loader.load(parent, func_names.at(i).c_str());
284         ASSERT_NE(returned_func_ppiiffccc, nullptr);
285         EXPECT_NEAR(
286             -1337.0,
287             returned_func_ppiiffccc(handle, &layer, func_names.at(i).c_str(), &x, &y, 200, 300, 0.123f, 1001.89f, 'a', 'b', 'c'),
288             0.001);
289         i++;
290     }
291 }
292 
293 template <typename FunctionLoader, typename ParentType, typename DispatchableHandleType, typename FunctionStruct>
check_layer_custom_functions_no_interception(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle, TestLayer& layer, FunctionStruct const&, std::vector<std::string>& func_names, uint32_t function_count, uint32_t function_start = 0)294 void check_layer_custom_functions_no_interception(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle,
295                                                   TestLayer& layer, FunctionStruct const&, std::vector<std::string>& func_names,
296                                                   uint32_t function_count, uint32_t function_start = 0) {
297     for (uint32_t i = function_start; i < function_start + function_count;) {
298         decltype(FunctionStruct::func_zero)* returned_func_i = loader.load(parent, func_names.at(i).c_str());
299         ASSERT_NE(returned_func_i, nullptr);
300         EXPECT_EQ(returned_func_i(handle, &layer, func_names.at(i).c_str(), i), (i)*3);
301         i++;
302         decltype(FunctionStruct::func_one)* returned_func_if = loader.load(parent, func_names.at(i).c_str());
303         ASSERT_NE(returned_func_if, nullptr);
304         EXPECT_EQ(returned_func_if(handle, &layer, func_names.at(i).c_str(), i, i + 1.f), (i)*3 + (i + 1) * 10);
305         i++;
306 
307         decltype(FunctionStruct::func_two)* returned_func_iif = loader.load(parent, func_names.at(i).c_str());
308         ASSERT_NE(returned_func_iif, nullptr);
309         EXPECT_NEAR(returned_func_iif(handle, &layer, func_names.at(i).c_str(), i * 10, i * 5, 0.1234f),
310                     (i * 10) + (i * 5) + (0.1234f), 0.001);
311         i++;
312 
313         int x = 5 + i;
314         int y = -505 - i;
315         decltype(FunctionStruct::func_three)* returned_func_pp = loader.load(parent, func_names.at(i).c_str());
316         ASSERT_NE(returned_func_pp, nullptr);
317         EXPECT_EQ(returned_func_pp(handle, &layer, func_names.at(i).c_str(), &x, &y),
318                   (5 + static_cast<int>(i)) + (-505 - static_cast<int>(i)));
319         i++;
320 
321         x = 5;
322         y = -505;
323         decltype(FunctionStruct::func_four)* returned_func_ppiiffccc = loader.load(parent, func_names.at(i).c_str());
324         ASSERT_NE(returned_func_ppiiffccc, nullptr);
325         EXPECT_NEAR(
326             returned_func_ppiiffccc(handle, &layer, func_names.at(i).c_str(), &x, &y, 200, 300, 0.123f, 1001.89f, 'a', 'b', 'c'),
327             -500 + (200) + (300) + (0.123) + (1001.89) + 97 + 98 + 99, 0.001f);
328         i++;
329     }
330 }
331 
332 using custom_physical_device_functions = custom_functions<VkPhysicalDevice>;
333 using layer_intercept_physical_device_functions = layer_intercept_functions<VkPhysicalDevice>;
334 using layer_implementation_physical_device_functions = layer_implementation_functions<VkPhysicalDevice>;
335 
TEST(UnknownFunction, PhysicalDeviceFunction)336 TEST(UnknownFunction, PhysicalDeviceFunction) {
337     FrameworkEnvironment env{};
338     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
339     uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
340     std::vector<std::string> function_names;
341     add_function_names(function_names, function_count);
342 
343     fill_implementation_functions(driver.physical_devices.at(0).custom_physical_device_functions, function_names,
344                                   custom_physical_device_functions{}, function_count);
345     InstWrapper inst{env.vulkan_functions};
346     inst.CheckCreate();
347 
348     VkPhysicalDevice phys_dev = inst.GetPhysDev();
349     check_custom_functions(env.vulkan_functions, inst.inst, phys_dev, custom_physical_device_functions{}, function_names,
350                            function_count);
351 }
352 
TEST(UnknownFunction, PhysicalDeviceFunctionMultipleDriverSupport)353 TEST(UnknownFunction, PhysicalDeviceFunctionMultipleDriverSupport) {
354     FrameworkEnvironment env{};
355     auto& driver_0 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
356     auto& driver_1 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
357     uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
358     std::vector<std::string> function_names;
359     add_function_names(function_names, function_count);
360 
361     // used to identify the GPUs
362     driver_0.physical_devices.emplace_back("physical_device_0").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
363     driver_1.physical_devices.emplace_back("physical_device_1").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
364 
365     for (uint32_t i = 0; i < function_count / 10; i++) {
366         fill_implementation_functions(driver_0.physical_devices.at(0).custom_physical_device_functions, function_names,
367                                       custom_physical_device_functions{}, 5, i * 10);
368         fill_implementation_functions(driver_1.physical_devices.at(0).custom_physical_device_functions, function_names,
369                                       custom_physical_device_functions{}, 5, i * 10 + 5);
370     }
371     InstWrapper inst{env.vulkan_functions};
372     inst.CheckCreate();
373 
374     auto phys_devs = inst.GetPhysDevs(2);
375     VkPhysicalDevice phys_dev_0 = phys_devs[0];
376     VkPhysicalDevice phys_dev_1 = phys_devs[1];
377     VkPhysicalDeviceProperties props{};
378     env.vulkan_functions.vkGetPhysicalDeviceProperties(phys_devs[0], &props);
379     if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
380         phys_dev_0 = phys_devs[1];
381         phys_dev_1 = phys_devs[0];
382     }
383     for (uint32_t i = 0; i < function_count / 10; i++) {
384         check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_0, custom_physical_device_functions{}, function_names, 5,
385                                i * 10);
386         check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_1, custom_physical_device_functions{}, function_names, 5,
387                                i * 10 + 5);
388     }
389 }
390 
391 // Add unknown functions to driver 0, and try to use them on driver 1.
TEST(UnknownFunctionDeathTests, PhysicalDeviceFunctionErrorPath)392 TEST(UnknownFunctionDeathTests, PhysicalDeviceFunctionErrorPath) {
393     FrameworkEnvironment env{};
394     auto& driver_0 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
395     auto& driver_1 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
396     std::vector<std::string> function_names;
397     add_function_names(function_names, 1);
398 
399     // used to identify the GPUs
400     driver_0.physical_devices.emplace_back("physical_device_0").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
401     driver_1.physical_devices.emplace_back("physical_device_1").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
402     function_names.push_back(std::string("vkNotIntRealFuncTEST_0"));
403 
404     custom_physical_device_functions funcs{};
405     driver_0.physical_devices.at(0).custom_physical_device_functions.push_back(
406         VulkanFunction{function_names.back(), to_vkVoidFunction(funcs.func_zero)});
407 
408     InstWrapper inst{env.vulkan_functions};
409     inst.CheckCreate();
410 
411     auto phys_devs = inst.GetPhysDevs(2);
412     VkPhysicalDevice phys_dev_to_use = phys_devs[1];
413     VkPhysicalDeviceProperties props{};
414     env.vulkan_functions.vkGetPhysicalDeviceProperties(phys_devs[1], &props);
415     if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) phys_dev_to_use = phys_devs[0];
416     // use the wrong GPU to query the functions, should get 5 errors
417 
418     decltype(custom_physical_device_functions::func_zero)* returned_func_i =
419         env.vulkan_functions.load(inst.inst, function_names.at(0).c_str());
420     ASSERT_NE(returned_func_i, nullptr);
421     ASSERT_DEATH(returned_func_i(phys_dev_to_use, 0), "Function vkNotIntRealFuncTEST_0 not supported for this physical device");
422 }
423 
TEST(UnknownFunction, PhysicalDeviceFunctionWithImplicitLayerImplementation)424 TEST(UnknownFunction, PhysicalDeviceFunctionWithImplicitLayerImplementation) {
425     FrameworkEnvironment env{};
426     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
427     uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
428     std::vector<std::string> function_names;
429     add_function_names(function_names, function_count);
430 
431     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
432                                                          .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
433                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
434                                                          .set_disable_environment("DISABLE_ME")),
435                            "implicit_layer_unknown_function_intercept.json");
436     auto& layer = env.get_test_layer();
437     fill_implementation_functions(layer.custom_physical_device_implementation_functions, function_names,
438                                   layer_implementation_physical_device_functions{}, function_count);
439 
440     InstWrapper inst{env.vulkan_functions};
441     inst.CheckCreate();
442 
443     VkPhysicalDevice phys_dev = inst.GetPhysDev();
444     check_layer_custom_functions_no_interception(env.vulkan_functions, inst.inst, phys_dev, layer,
445                                                  layer_implementation_physical_device_functions{}, function_names, function_count);
446 }
447 
TEST(UnknownFunction, PhysicalDeviceFunctionMultipleDriverSupportWithImplicitLayerImplementation)448 TEST(UnknownFunction, PhysicalDeviceFunctionMultipleDriverSupportWithImplicitLayerImplementation) {
449     FrameworkEnvironment env{};
450     auto& driver_0 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
451     auto& driver_1 = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
452     uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
453     std::vector<std::string> function_names;
454     add_function_names(function_names, function_count);
455 
456     // used to identify the GPUs
457     driver_0.physical_devices.emplace_back("physical_device_0").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
458     driver_1.physical_devices.emplace_back("physical_device_1").properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
459     for (uint32_t i = 0; i < function_count / 10; i++) {
460         fill_implementation_functions(driver_0.physical_devices.at(0).custom_physical_device_functions, function_names,
461                                       custom_physical_device_functions{}, 5, i * 10);
462         fill_implementation_functions(driver_1.physical_devices.at(0).custom_physical_device_functions, function_names,
463                                       custom_physical_device_functions{}, 5, i * 10 + 5);
464     }
465 
466     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
467                                                          .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
468                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
469                                                          .set_disable_environment("DISABLE_ME")),
470                            "implicit_layer_unknown_function_intercept.json");
471 
472     InstWrapper inst{env.vulkan_functions};
473     inst.CheckCreate();
474 
475     auto phys_devs = inst.GetPhysDevs(2);
476     VkPhysicalDevice phys_dev_0 = phys_devs[0];
477     VkPhysicalDevice phys_dev_1 = phys_devs[1];
478     VkPhysicalDeviceProperties props{};
479     env.vulkan_functions.vkGetPhysicalDeviceProperties(phys_devs[0], &props);
480     if (props.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
481         phys_dev_0 = phys_devs[1];
482         phys_dev_1 = phys_devs[0];
483     }
484     for (uint32_t i = 0; i < function_count / 10; i++) {
485         check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_0, custom_physical_device_functions{}, function_names, 5,
486                                i * 10);
487         check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_1, custom_physical_device_functions{}, function_names, 5,
488                                i * 10 + 5);
489     }
490 }
491 
TEST(UnknownFunction, PhysicalDeviceFunctionWithImplicitLayerInterception)492 TEST(UnknownFunction, PhysicalDeviceFunctionWithImplicitLayerInterception) {
493     FrameworkEnvironment env{};
494     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
495     uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
496 
497     std::vector<std::string> function_names;
498     add_function_names(function_names, function_count);
499 
500     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
501                                                          .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
502                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
503                                                          .set_disable_environment("DISABLE_ME")),
504                            "implicit_layer_unknown_function_intercept.json");
505     auto& layer = env.get_test_layer();
506     fill_phys_dev_intercept_functions(layer, function_names, layer_intercept_physical_device_functions{}, function_count);
507 
508     InstWrapper inst{env.vulkan_functions};
509     inst.CheckCreate();
510 
511     VkPhysicalDevice phys_dev = inst.GetPhysDev();
512     check_layer_custom_functions_no_implementation(env.vulkan_functions, inst.inst, phys_dev, layer,
513                                                    layer_intercept_physical_device_functions{}, function_names, function_count);
514 }
515 
TEST(UnknownFunction, PhysicalDeviceFunctionDriverSupportWithImplicitLayerInterception)516 TEST(UnknownFunction, PhysicalDeviceFunctionDriverSupportWithImplicitLayerInterception) {
517     FrameworkEnvironment env{};
518     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
519     uint32_t function_count = 100;
520     std::vector<std::string> function_names;
521     add_function_names(function_names, function_count);
522     fill_implementation_functions(driver.physical_devices.at(0).custom_physical_device_functions, function_names,
523                                   layer_implementation_physical_device_functions{}, function_count);
524     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
525                                                          .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
526                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
527                                                          .set_disable_environment("DISABLE_ME")),
528                            "implicit_layer_unknown_function_intercept.json");
529     auto& layer = env.get_test_layer();
530     fill_phys_dev_intercept_functions(layer, function_names, layer_intercept_physical_device_functions{}, function_count);
531 
532     InstWrapper inst{env.vulkan_functions};
533     inst.CheckCreate();
534 
535     VkPhysicalDevice phys_dev = inst.GetPhysDev();
536     check_layer_custom_functions(env.vulkan_functions, inst.inst, phys_dev, layer, layer_intercept_physical_device_functions{},
537                                  function_names, function_count);
538 }
539 
TEST(UnknownFunction, PhysicalDeviceFunctionWithMultipleImplicitLayersInterception)540 TEST(UnknownFunction, PhysicalDeviceFunctionWithMultipleImplicitLayersInterception) {
541     FrameworkEnvironment env{};
542     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
543     std::vector<std::string> function_names;
544     uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
545     add_function_names(function_names, function_count);
546     driver.physical_devices.emplace_back("physical_device_0");
547 
548     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
549                                                          .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_0")
550                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
551                                                          .set_disable_environment("DISABLE_ME")),
552                            "implicit_layer_unknown_function_intercept_0.json");
553     auto& layer_0 = env.get_test_layer(0);
554     layer_0.set_use_gipa_GetPhysicalDeviceProcAddr(true);
555     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
556                                                          .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_1")
557                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
558                                                          .set_disable_environment("DISABLE_ME")),
559                            "implicit_layer_unknown_function_intercept_1.json");
560     auto& layer_1 = env.get_test_layer(1);
561     layer_1.set_use_gipa_GetPhysicalDeviceProcAddr(false);
562     for (uint32_t i = 0; i < function_count / 10; i++) {
563         fill_implementation_functions(driver.physical_devices.at(0).custom_physical_device_functions, function_names,
564                                       layer_implementation_physical_device_functions{}, 5, i * 10);
565         fill_phys_dev_intercept_functions(layer_0, function_names, layer_intercept_physical_device_functions{}, 5, i * 10);
566         fill_phys_dev_intercept_functions(layer_1, function_names, layer_intercept_physical_device_functions{}, 5, i * 10 + 5);
567     }
568     InstWrapper inst{env.vulkan_functions};
569     inst.CheckCreate();
570 
571     VkPhysicalDevice phys_dev = inst.GetPhysDev();
572     for (uint32_t i = 0; i < function_count / 10; i++) {
573         check_layer_custom_functions(env.vulkan_functions, inst.inst, phys_dev, layer_0,
574                                      layer_intercept_physical_device_functions{}, function_names, 5, i * 10);
575         check_layer_custom_functions_no_implementation(env.vulkan_functions, inst.inst, phys_dev, layer_1,
576                                                        layer_intercept_physical_device_functions{}, function_names, 5, i * 10 + 5);
577     }
578 }
579 
580 template <typename ParentType>
581 ParentType get_parent_type(InstWrapper const& inst, DeviceWrapper const& dev);
582 
583 template <>
get_parent_type(InstWrapper const& inst, DeviceWrapper const&)584 VkInstance get_parent_type<VkInstance>(InstWrapper const& inst, DeviceWrapper const&) {
585     return inst.inst;
586 }
587 template <>
get_parent_type(InstWrapper const&, DeviceWrapper const& dev)588 VkDevice get_parent_type<VkDevice>(InstWrapper const&, DeviceWrapper const& dev) {
589     return dev.dev;
590 }
591 
592 template <typename DispatchableHandleType>
593 DispatchableHandleType get_dispatch_handle(FrameworkEnvironment& env, DeviceWrapper const& dev,
594                                            std::vector<TestConfig> const& flags);
595 
596 template <>
get_dispatch_handle(FrameworkEnvironment&, DeviceWrapper const& dev, std::vector<TestConfig> const&)597 VkDevice get_dispatch_handle<VkDevice>(FrameworkEnvironment&, DeviceWrapper const& dev, std::vector<TestConfig> const&) {
598     return dev.dev;
599 }
600 
601 template <>
get_dispatch_handle(FrameworkEnvironment& env, DeviceWrapper const& dev, std::vector<TestConfig> const&)602 VkCommandBuffer get_dispatch_handle<VkCommandBuffer>(FrameworkEnvironment& env, DeviceWrapper const& dev,
603                                                      std::vector<TestConfig> const&) {
604     VkCommandPool command_pool;
605     VkCommandPoolCreateInfo pool_create_info{};
606     DeviceFunctions funcs{env.vulkan_functions, dev};
607     funcs.vkCreateCommandPool(dev, &pool_create_info, nullptr, &command_pool);
608     VkCommandBuffer command_buffer;
609     VkCommandBufferAllocateInfo alloc_info{};
610     alloc_info.commandBufferCount = 1;
611     alloc_info.commandPool = command_pool;
612     funcs.vkAllocateCommandBuffers(dev, &alloc_info, &command_buffer);
613     return command_buffer;
614 }
615 
616 template <>
get_dispatch_handle(FrameworkEnvironment& env, DeviceWrapper const& dev, std::vector<TestConfig> const&)617 VkQueue get_dispatch_handle<VkQueue>(FrameworkEnvironment& env, DeviceWrapper const& dev, std::vector<TestConfig> const&) {
618     DeviceFunctions funcs{env.vulkan_functions, dev.dev};
619     VkQueue queue;
620     funcs.vkGetDeviceQueue(dev, 0, 0, &queue);
621     return queue;
622 }
623 
624 template <typename ParentType, typename DispatchableHandleType>
unknown_function_test_impl(std::vector<TestConfig> const& flags)625 void unknown_function_test_impl(std::vector<TestConfig> const& flags) {
626     using custom_functions_type = custom_functions<DispatchableHandleType>;
627     using layer_implementation_functions_type = layer_implementation_functions<DispatchableHandleType>;
628     using layer_intercept_functions_type = layer_intercept_functions<DispatchableHandleType>;
629 
630     FrameworkEnvironment env{};
631     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
632     uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
633 
634     std::vector<std::string> function_names;
635     add_function_names(function_names, function_count);
636 
637     if (has_flag(flags, TestConfig::add_layer_interception)) {
638         fill_implementation_functions(driver.physical_devices.back().known_device_functions, function_names,
639                                       layer_implementation_functions_type{}, function_count);
640     } else {
641         fill_implementation_functions(driver.physical_devices.back().known_device_functions, function_names,
642                                       custom_functions_type{}, function_count);
643     }
644     TestLayer* layer_ptr = nullptr;
645     if (has_flag(flags, TestConfig::add_layer_implementation) || has_flag(flags, TestConfig::add_layer_interception)) {
646         env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
647                                                              .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
648                                                              .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
649                                                              .set_disable_environment("DISABLE_ME")),
650                                "implicit_layer_unknown_function_intercept.json");
651         layer_ptr = &env.get_test_layer();
652     }
653     if (has_flag(flags, TestConfig::add_layer_implementation) && has_flag(flags, TestConfig::add_layer_interception)) {
654         for (uint32_t i = 0; i < function_count / 10; i++) {
655             fill_implementation_functions(layer_ptr->custom_device_implementation_functions, function_names,
656                                           layer_implementation_functions_type{}, 5, i * 10);
657             fill_device_intercept_functions(*layer_ptr, function_names, layer_intercept_functions_type{}, 5, i * 10 + 5);
658         }
659     } else if (has_flag(flags, TestConfig::add_layer_implementation)) {
660         fill_implementation_functions(layer_ptr->custom_device_implementation_functions, function_names, custom_functions_type{},
661                                       function_count);
662     } else if (has_flag(flags, TestConfig::add_layer_interception)) {
663         fill_device_intercept_functions(*layer_ptr, function_names, layer_intercept_functions_type{}, function_count);
664     }
665 
666     InstWrapper inst{env.vulkan_functions};
667     inst.CheckCreate();
668 
669     DeviceWrapper dev{inst};
670     dev.create_info.add_device_queue({});
671     dev.CheckCreate(inst.GetPhysDev());
672     auto dispatch_type = get_dispatch_handle<DispatchableHandleType>(env, dev, flags);
673     auto parent_type = get_parent_type<ParentType>(inst, dev);
674 
675     if (has_flag(flags, TestConfig::add_layer_implementation) && has_flag(flags, TestConfig::add_layer_interception)) {
676         for (uint32_t i = 0; i < function_count / 10; i++) {
677             check_layer_custom_functions_no_interception(env.vulkan_functions, parent_type, dispatch_type, *layer_ptr,
678                                                          layer_implementation_functions_type{}, function_names, 5, i * 10);
679         }
680     } else if (has_flag(flags, TestConfig::add_layer_interception)) {
681         check_layer_custom_functions(env.vulkan_functions, parent_type, dispatch_type, *layer_ptr, layer_intercept_functions_type{},
682                                      function_names, function_count);
683 
684     } else {
685         check_custom_functions(env.vulkan_functions, parent_type, dispatch_type, custom_functions_type{}, function_names,
686                                function_count);
687     }
688 }
689 
690 // Device
691 
TEST(UnknownFunction, DeviceFromGDPA)692 TEST(UnknownFunction, DeviceFromGDPA) { unknown_function_test_impl<VkDevice, VkDevice>({}); }
693 
TEST(UnknownFunction, DeviceFromGDPAWithLayerImplementation)694 TEST(UnknownFunction, DeviceFromGDPAWithLayerImplementation) {
695     unknown_function_test_impl<VkDevice, VkDevice>({TestConfig::add_layer_implementation});
696 }
697 
TEST(UnknownFunction, DeviceFromGDPAWithLayerInterception)698 TEST(UnknownFunction, DeviceFromGDPAWithLayerInterception) {
699     unknown_function_test_impl<VkDevice, VkDevice>({TestConfig::add_layer_interception});
700 }
701 
TEST(UnknownFunction, DeviceFromGDPAWithLayerInterceptionAndLayerImplementation)702 TEST(UnknownFunction, DeviceFromGDPAWithLayerInterceptionAndLayerImplementation) {
703     unknown_function_test_impl<VkDevice, VkDevice>({TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
704 }
705 
TEST(UnknownFunction, DeviceFromGIPA)706 TEST(UnknownFunction, DeviceFromGIPA) { unknown_function_test_impl<VkInstance, VkDevice>({}); }
707 
TEST(UnknownFunction, DeviceFromGIPAWithLayerImplementation)708 TEST(UnknownFunction, DeviceFromGIPAWithLayerImplementation) {
709     unknown_function_test_impl<VkInstance, VkDevice>({TestConfig::add_layer_implementation});
710 }
711 
TEST(UnknownFunction, DeviceFromGIPAWithLayerInterception)712 TEST(UnknownFunction, DeviceFromGIPAWithLayerInterception) {
713     unknown_function_test_impl<VkInstance, VkDevice>({TestConfig::add_layer_implementation});
714 }
715 
TEST(UnknownFunction, DeviceFromGIPAWithLayerInterceptionAndLayerImplementation)716 TEST(UnknownFunction, DeviceFromGIPAWithLayerInterceptionAndLayerImplementation) {
717     unknown_function_test_impl<VkInstance, VkDevice>({TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
718 }
719 
720 // Command buffers
721 
TEST(UnknownFunction, CommandBufferFromGDPA)722 TEST(UnknownFunction, CommandBufferFromGDPA) { unknown_function_test_impl<VkDevice, VkCommandBuffer>({}); }
723 
TEST(UnknownFunction, CommandBufferFromGDPAWithLayerImplementation)724 TEST(UnknownFunction, CommandBufferFromGDPAWithLayerImplementation) {
725     unknown_function_test_impl<VkDevice, VkCommandBuffer>({TestConfig::add_layer_implementation});
726 }
727 
TEST(UnknownFunction, CommandBufferFromGDPAWithLayerInterception)728 TEST(UnknownFunction, CommandBufferFromGDPAWithLayerInterception) {
729     unknown_function_test_impl<VkDevice, VkCommandBuffer>({TestConfig::add_layer_interception});
730 }
731 
TEST(UnknownFunction, CommandBufferFromGDPAWithLayerInterceptionAndLayerImplementation)732 TEST(UnknownFunction, CommandBufferFromGDPAWithLayerInterceptionAndLayerImplementation) {
733     unknown_function_test_impl<VkDevice, VkCommandBuffer>(
734         {TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
735 }
736 
TEST(UnknownFunction, CommandBufferFromGIPA)737 TEST(UnknownFunction, CommandBufferFromGIPA) { unknown_function_test_impl<VkInstance, VkCommandBuffer>({}); }
738 
TEST(UnknownFunction, CommandBufferFromGIPAWithLayerImplementation)739 TEST(UnknownFunction, CommandBufferFromGIPAWithLayerImplementation) {
740     unknown_function_test_impl<VkInstance, VkCommandBuffer>({TestConfig::add_layer_implementation});
741 }
742 
TEST(UnknownFunction, CommandBufferFromGIPAWithLayerInterception)743 TEST(UnknownFunction, CommandBufferFromGIPAWithLayerInterception) {
744     unknown_function_test_impl<VkInstance, VkCommandBuffer>({TestConfig::add_layer_implementation});
745 }
746 
TEST(UnknownFunction, CommandBufferFromGIPAWithLayerInterceptionAndLayerImplementation)747 TEST(UnknownFunction, CommandBufferFromGIPAWithLayerInterceptionAndLayerImplementation) {
748     unknown_function_test_impl<VkInstance, VkCommandBuffer>(
749         {TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
750 }
751 
752 // Queues
753 
TEST(UnknownFunction, QueueFromGDPA)754 TEST(UnknownFunction, QueueFromGDPA) { unknown_function_test_impl<VkDevice, VkQueue>({}); }
755 
TEST(UnknownFunction, QueueFromGDPAWithLayerImplementation)756 TEST(UnknownFunction, QueueFromGDPAWithLayerImplementation) {
757     unknown_function_test_impl<VkDevice, VkQueue>({TestConfig::add_layer_implementation});
758 }
759 
TEST(UnknownFunction, QueueFromGDPAWithLayerInterception)760 TEST(UnknownFunction, QueueFromGDPAWithLayerInterception) {
761     unknown_function_test_impl<VkDevice, VkQueue>({TestConfig::add_layer_interception});
762 }
763 
TEST(UnknownFunction, QueueFromGDPAWithLayerInterceptionAndLayerImplementation)764 TEST(UnknownFunction, QueueFromGDPAWithLayerInterceptionAndLayerImplementation) {
765     unknown_function_test_impl<VkDevice, VkQueue>({TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
766 }
767 
TEST(UnknownFunction, QueueFromGIPA)768 TEST(UnknownFunction, QueueFromGIPA) { unknown_function_test_impl<VkInstance, VkQueue>({}); }
769 
TEST(UnknownFunction, QueueFromGIPAWithLayer)770 TEST(UnknownFunction, QueueFromGIPAWithLayer) {
771     unknown_function_test_impl<VkInstance, VkQueue>({TestConfig::add_layer_implementation});
772 }
773 
TEST(UnknownFunction, QueueFromGIPAWithLayerInterception)774 TEST(UnknownFunction, QueueFromGIPAWithLayerInterception) {
775     unknown_function_test_impl<VkInstance, VkQueue>({TestConfig::add_layer_implementation});
776 }
777 
TEST(UnknownFunction, QueueFromGIPAWithLayerInterceptionAndLayerImplementation)778 TEST(UnknownFunction, QueueFromGIPAWithLayerInterceptionAndLayerImplementation) {
779     unknown_function_test_impl<VkInstance, VkQueue>({TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
780 }
781 
782 /*
783  The purpose of LayerInterceptData is to provide a place to store data that is accessible inside the interception function.
784  It works by being a templated type with static variables. Every unique type used creates a new template instantiation, with its own
785  static variable storage. Thus interception functions that are templated correctly have per-template static data storage at their
786  disposal, which is used to query the next function in the chain and call down.
787 */
788 
789 template <typename UniqueType>
790 struct LayerInterceptData {
791     static TestLayer* layer;
792     static const char* name;
793 };
794 template <typename UniqueType>
795 TestLayer* LayerInterceptData<UniqueType>::layer = nullptr;
796 template <typename UniqueType>
797 const char* LayerInterceptData<UniqueType>::name = nullptr;
798 
799 template <typename DispatchableHandle>
800 struct FunctionZero {
implementationFunctionZero801     static VKAPI_ATTR uint32_t VKAPI_CALL implementation(DispatchableHandle, uint32_t a, uint32_t b) { return a + b; }
802 
803     template <typename LayerType>
interceptFunctionZero804     static VKAPI_ATTR uint32_t VKAPI_CALL intercept(DispatchableHandle handle, uint32_t a, uint32_t b) {
805         decltype(implementation)* func =
806             reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
807         if (func == nullptr) return 1337;
808         return func(handle, a + 3, b + 7);
809     }
810 
811     template <typename ParentType>
checkFunctionZero812     static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
813                       uint32_t interception_count = 1) {
814         decltype(implementation)* returned_func = loader.load(parent, name);
815         ASSERT_NE(returned_func, nullptr);
816         EXPECT_EQ(returned_func(dispatch_type, 4, 9), (4 + 3 * interception_count) + (9 + 7 * interception_count));
817     }
818     template <typename ParentType>
check_no_implementationFunctionZero819     static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
820                                         const char* name) {
821         decltype(implementation)* returned_func = loader.load(parent, name);
822         ASSERT_NE(returned_func, nullptr);
823         EXPECT_EQ(returned_func(dispatch_type, 5, 2), 1337U);
824     }
825 };
826 
827 template <typename DispatchableHandle>
828 struct FunctionOne {
implementationFunctionOne829     static VKAPI_ATTR uint32_t VKAPI_CALL implementation(DispatchableHandle, uint32_t a, uint32_t b, char c) { return a + b + c; }
830 
831     template <typename LayerType>
interceptFunctionOne832     static VKAPI_ATTR uint32_t VKAPI_CALL intercept(DispatchableHandle handle, uint32_t a, uint32_t b, char c) {
833         decltype(implementation)* func =
834             reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
835         if (func == nullptr) return 1337;
836         return func(handle, a + 2, b + 9, c + 1);
837     }
838 
839     template <typename ParentType>
checkFunctionOne840     static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
841                       uint32_t interception_count = 1) {
842         decltype(implementation)* returned_func = loader.load(parent, name);
843         ASSERT_NE(returned_func, nullptr);
844         EXPECT_EQ(returned_func(dispatch_type, 12, 17, 'a'),
845                   (12 + 2 * interception_count) + (17 + 9 * interception_count) + ('a' + 1 * interception_count));
846     }
847     template <typename ParentType>
check_no_implementationFunctionOne848     static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
849                                         const char* name) {
850         decltype(implementation)* returned_func = loader.load(parent, name);
851         ASSERT_NE(returned_func, nullptr);
852         EXPECT_EQ(returned_func(dispatch_type, 1, 516, 'c'), 1337U);
853     }
854 };
855 
856 template <typename DispatchableHandle>
857 struct FunctionTwo {
implementationFunctionTwo858     static VKAPI_ATTR float VKAPI_CALL implementation(DispatchableHandle, int* ptr_a, int* ptr_b) {
859         return 0.123f + *ptr_a + *ptr_b;
860     }
861 
862     template <typename LayerType>
interceptFunctionTwo863     static VKAPI_ATTR float VKAPI_CALL intercept(DispatchableHandle handle, int* ptr_a, int* ptr_b) {
864         decltype(implementation)* func =
865             reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
866         if (func == nullptr) return -1337.f;
867         *ptr_a += 2;
868         *ptr_b += 5;
869         return func(handle, ptr_a, ptr_b);
870     }
871 
872     template <typename ParentType>
checkFunctionTwo873     static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
874                       uint32_t interception_count = 1) {
875         decltype(implementation)* returned_func = loader.load(parent, name);
876         ASSERT_NE(returned_func, nullptr);
877         int x = 10, y = 3;
878         EXPECT_NEAR(returned_func(dispatch_type, &x, &y), 0.123f + (10 + 2 * interception_count) + (3 + 5 * interception_count),
879                     0.001);
880     }
881     template <typename ParentType>
check_no_implementationFunctionTwo882     static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
883                                         const char* name) {
884         decltype(implementation)* returned_func = loader.load(parent, name);
885         ASSERT_NE(returned_func, nullptr);
886         int x = 10, y = 0;
887         EXPECT_NEAR(returned_func(dispatch_type, &x, &y), -1337.f, 0.001);
888     }
889 };
890 
891 template <typename DispatchableHandle>
892 struct FunctionThree {
implementationFunctionThree893     static VKAPI_ATTR float VKAPI_CALL implementation(DispatchableHandle, int* ptr_a, float* ptr_b, uint32_t c) {
894         return 0.456f + *ptr_a + *ptr_b + c;
895     }
896 
897     template <typename LayerType>
interceptFunctionThree898     static VKAPI_ATTR float VKAPI_CALL intercept(DispatchableHandle handle, int* ptr_a, float* ptr_b, uint32_t c) {
899         decltype(implementation)* func =
900             reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
901         if (func == nullptr) return -1837.f;
902         *ptr_a += 55;
903         *ptr_b += 5.98f;
904         return func(handle, ptr_a, ptr_b, c + 100);
905     }
906 
907     template <typename ParentType>
checkFunctionThree908     static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
909                       uint32_t interception_count = 1) {
910         decltype(implementation)* returned_func = loader.load(parent, name);
911         ASSERT_NE(returned_func, nullptr);
912         int x = 96;
913         float y = 7;
914         EXPECT_NEAR(returned_func(dispatch_type, &x, &y, 30),
915                     0.456f + (96 + 55 * interception_count) + (7 + 5.98f * interception_count) + (30 + 100 * interception_count),
916                     0.001);
917     }
918     template <typename ParentType>
check_no_implementationFunctionThree919     static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
920                                         const char* name) {
921         decltype(implementation)* returned_func = loader.load(parent, name);
922         ASSERT_NE(returned_func, nullptr);
923         int x = 10;
924         float y = 0;
925         EXPECT_NEAR(returned_func(dispatch_type, &x, &y, 40), -1837.f, 0.001);
926     }
927 };
928 
929 template <typename DispatchableHandle>
930 struct FunctionFour {
implementationFunctionFour931     static VKAPI_ATTR VkResult VKAPI_CALL implementation(DispatchableHandle, VkPhysicalDeviceLimits* limits, uint32_t* count,
932                                                          VkExtensionProperties* props) {
933         limits->nonCoherentAtomSize = 0x0000ABCD0000FEDCU;
934         if (props == nullptr) {
935             *count = 5;
936             return VK_INCOMPLETE;
937         } else {
938             for (uint32_t i = 0; i < *count; i++) {
939                 props[i].specVersion = i;
940             }
941             return VK_SUCCESS;
942         }
943     }
944 
945     template <typename LayerType>
interceptFunctionFour946     static VKAPI_ATTR VkResult VKAPI_CALL intercept(DispatchableHandle handle, VkPhysicalDeviceLimits* limits, uint32_t* count,
947                                                     VkExtensionProperties* props) {
948         decltype(implementation)* func =
949             reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
950         if (func == nullptr) return VK_ERROR_DEVICE_LOST;
951         VkResult res = func(handle, limits, count, props);
952         if (props) {
953             for (uint32_t i = 5; i < *count; i++) {
954                 props[i].specVersion = 1234 + i * 2;
955             }
956         } else if (count) {
957             *count += 1;
958         }
959         return res;
960     }
961 
962     template <typename ParentType>
checkFunctionFour963     static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
964                       uint32_t interception_count = 1) {
965         decltype(implementation)* returned_func = loader.load(parent, name);
966         ASSERT_NE(returned_func, nullptr);
967         VkPhysicalDeviceLimits limits{};
968         uint32_t count = 0;
969         EXPECT_EQ(returned_func(dispatch_type, &limits, &count, nullptr), VK_INCOMPLETE);
970         EXPECT_EQ(count, 5 + interception_count);
971         std::vector<VkExtensionProperties> props(count, VkExtensionProperties{});
972         EXPECT_EQ(returned_func(dispatch_type, &limits, &count, props.data()), VK_SUCCESS);
973         for (uint32_t i = 0; i < 5; i++) {
974             EXPECT_EQ(props.at(i).specVersion, i);
975         }
976         for (uint32_t i = 5; i < interception_count; i++) {
977             EXPECT_EQ(props.at(i).specVersion, 1234 + i * 2);  // interception should do this
978         }
979     }
980     template <typename ParentType>
check_no_implementationFunctionFour981     static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
982                                         const char* name) {
983         decltype(implementation)* returned_func = loader.load(parent, name);
984         ASSERT_NE(returned_func, nullptr);
985         VkPhysicalDeviceLimits limits{};
986         EXPECT_EQ(returned_func(dispatch_type, &limits, nullptr, nullptr), VK_ERROR_DEVICE_LOST);
987     }
988 };
989 
990 struct UnknownFunction {
991     std::string name;
992 
993     bool has_implementation = false;
994     std::vector<uint32_t> interception_stack;
995 
996     UnknownFunction() = default;
UnknownFunctionUnknownFunction997     UnknownFunction(std::string name) : name(name) {}
998 
999     template <typename FunctionType, typename ParentType, typename DispatchableHandle>
checkUnknownFunction1000     void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type) {
1001         if (has_implementation) {
1002             // Find how many layers intercept this function, stop if any layer 'implements' the function, thus doesn't return
1003             uint32_t intercept_count = 0;
1004             for (auto const& elem : interception_stack) {
1005                 if (elem == 1) break;
1006                 intercept_count++;
1007             }
1008             FunctionType::Function::check(loader, parent, dispatch_type, name.c_str(), intercept_count);
1009         } else {
1010             FunctionType::Function::check_no_implementation(loader, parent, dispatch_type, name.c_str());
1011         }
1012     }
1013 
push_layer_implementationUnknownFunction1014     void push_layer_implementation() { interception_stack.push_back(1); }
push_layer_interceptionUnknownFunction1015     void push_layer_interception() { interception_stack.push_back(0); }
1016 };
1017 
1018 // For VkDevice, VkCommandBuffer, & VkQueue
1019 template <typename FunctionType, typename DispatchableHandle>
1020 struct UnknownFunctionInfo {
1021     using Function = FunctionType;
1022 
add_to_driverUnknownFunctionInfo1023     static void add_to_driver(UnknownFunction& func, PhysicalDevice& physical_device) {
1024         physical_device.add_device_function({func.name.c_str(), to_vkVoidFunction(Function::implementation)});
1025         func.has_implementation = true;
1026     }
1027 
1028     template <typename LayerStruct>
add_to_layerUnknownFunctionInfo1029     static void add_to_layer(UnknownFunction& func, TestLayer& layer, LayerStruct) {
1030         LayerInterceptData<LayerStruct>::layer = &layer;
1031         LayerInterceptData<LayerStruct>::name = func.name.c_str();
1032         layer.add_custom_device_interception_function(
1033             func.name, to_vkVoidFunction(&Function::template intercept<LayerInterceptData<LayerStruct>>));
1034         func.push_layer_interception();
1035     }
1036 
add_implementation_to_layerUnknownFunctionInfo1037     static void add_implementation_to_layer(UnknownFunction& func, TestLayer& layer) {
1038         layer.add_custom_device_implementation_function({func.name.c_str(), to_vkVoidFunction(Function::implementation)});
1039         func.has_implementation = true;
1040         func.push_layer_implementation();
1041     }
1042 };
1043 
1044 // Specialization for VkPhysicalDevice
1045 
1046 template <typename FunctionType>
1047 struct UnknownFunctionInfo<FunctionType, VkPhysicalDevice> {
1048     using Function = FunctionType;
1049 
add_to_driverUnknownFunctionInfo1050     static void add_to_driver(UnknownFunction& func, PhysicalDevice& physical_device) {
1051         physical_device.add_custom_physical_device_function({func.name.c_str(), to_vkVoidFunction(Function::implementation)});
1052         func.has_implementation = true;
1053     }
1054 
1055     template <typename LayerStruct>
add_to_layerUnknownFunctionInfo1056     static void add_to_layer(UnknownFunction& func, TestLayer& layer, LayerStruct) {
1057         LayerInterceptData<LayerStruct>::layer = &layer;
1058         LayerInterceptData<LayerStruct>::name = func.name.c_str();
1059         layer.add_custom_physical_device_intercept_function(
1060             func.name, to_vkVoidFunction(&Function::template intercept<LayerInterceptData<LayerStruct>>));
1061         func.push_layer_interception();
1062     }
1063 
add_implementation_to_layerUnknownFunctionInfo1064     static void add_implementation_to_layer(UnknownFunction& func, TestLayer& layer) {
1065         layer.add_custom_physical_device_implementation_function({func.name.c_str(), to_vkVoidFunction(Function::implementation)});
1066         func.has_implementation = true;
1067         func.push_layer_implementation();
1068     }
1069 };
1070 
1071 struct Functions {
1072     template <template <typename> class Function>
1073     struct HelperTypedef {
1074         using physical_device = UnknownFunctionInfo<Function<VkPhysicalDevice>, VkPhysicalDevice>;
1075         using device = UnknownFunctionInfo<Function<VkDevice>, VkDevice>;
1076         using command_buffer = UnknownFunctionInfo<Function<VkCommandBuffer>, VkCommandBuffer>;
1077         using queue = UnknownFunctionInfo<Function<VkQueue>, VkQueue>;
1078     };
1079 
1080     using zero = HelperTypedef<FunctionZero>;
1081     using one = HelperTypedef<FunctionOne>;
1082     using two = HelperTypedef<FunctionTwo>;
1083     using three = HelperTypedef<FunctionThree>;
1084     using four = HelperTypedef<FunctionFour>;
1085 };
1086 
1087 template <size_t I>
1088 struct D {};
1089 
TEST(UnknownFunction, PhysicalDeviceFunctionTwoLayerInterception)1090 TEST(UnknownFunction, PhysicalDeviceFunctionTwoLayerInterception) {
1091     FrameworkEnvironment env{};
1092     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
1093     PhysicalDevice& pd = driver.physical_devices.back();
1094 
1095     UnknownFunction f{"vkFunc1"};
1096     Functions::three::physical_device::add_to_driver(f, pd);
1097 
1098     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1099                                                          .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
1100                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
1101                                                          .set_disable_environment("DISABLE_ME")),
1102                            "implicit_layer_unknown_function_intercept.json");
1103     auto& layer0 = env.get_test_layer(0);
1104     Functions::three::physical_device::add_to_layer(f, layer0, D<0>{});
1105 
1106     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1107                                                          .set_name("VK_LAYER_implicit_layer_unknown_function_intercept2")
1108                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
1109                                                          .set_disable_environment("DISABLE_ME")),
1110                            "implicit_layer_unknown_function_intercept2.json");
1111     auto& layer1 = env.get_test_layer(1);
1112 
1113     Functions::three::physical_device::add_to_layer(f, layer1, D<1>{});
1114 
1115     InstWrapper inst{env.vulkan_functions};
1116     inst.CheckCreate();
1117 
1118     VkPhysicalDevice phys_dev = inst.GetPhysDev();
1119 
1120     f.check<Functions::three::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
1121 }
1122 
TEST(UnknownFunction, ManyCombinations)1123 TEST(UnknownFunction, ManyCombinations) {
1124     FrameworkEnvironment env{};
1125     auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
1126     PhysicalDevice& physical_device = driver.physical_devices.back();
1127     std::vector<UnknownFunction> unknown_funcs;
1128 
1129     unknown_funcs.emplace_back("vkZero_uint32_uint32_0");
1130     unknown_funcs.emplace_back("vkOne_uint32_uint32_char_1");
1131     unknown_funcs.emplace_back("vkTwo_ptr_int_ptr_int_2");
1132     unknown_funcs.emplace_back("vkThree_ptr_int_ptr_float_uint_3");
1133     unknown_funcs.emplace_back("vkFour_PD_limits_ptr_uint_ptr_ExtProps_4");
1134     unknown_funcs.emplace_back("vkZero_uint32_uint32_5");
1135     unknown_funcs.emplace_back("vkOne_uint32_uint32_char_6");
1136     unknown_funcs.emplace_back("vkTwo_ptr_int_ptr_int_7");
1137     unknown_funcs.emplace_back("vkThree_ptr_int_ptr_float_uint_8");
1138     unknown_funcs.emplace_back("vkFour_PD_limits_ptr_uint_ptr_ExtProps_9");
1139     unknown_funcs.emplace_back("vkZero_uint32_uint32_10");
1140     unknown_funcs.emplace_back("vkOne_uint32_uint32_char_11");
1141     unknown_funcs.emplace_back("vkTwo_ptr_int_ptr_int_12");
1142 
1143     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1144                                                          .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_0")
1145                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
1146                                                          .set_disable_environment("DISABLE_ME")
1147                                                          .add_device_extension(ManifestLayer::LayerDescription::Extension{
1148                                                              "VK_EXT_for_the_laughs", 0, {"vkOne_uint32_uint32_char_11"}})),
1149                            "implicit_layer_unknown_function_intercept_0.json");
1150     auto& layer_0 = env.get_test_layer(0);
1151     layer_0.set_use_gipa_GetPhysicalDeviceProcAddr(true);
1152     env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
1153                                                          .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_1")
1154                                                          .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
1155                                                          .set_disable_environment("DISABLE_ME")),
1156                            "implicit_layer_unknown_function_intercept_1.json");
1157     auto& layer_1 = env.get_test_layer(1);
1158     layer_1.set_use_gipa_GetPhysicalDeviceProcAddr(false);
1159 
1160     // Physical Device functions
1161     Functions::zero::physical_device::add_to_driver(unknown_funcs.at(0), physical_device);
1162 
1163     Functions::one::physical_device::add_to_driver(unknown_funcs.at(1), physical_device);
1164     Functions::one::physical_device::add_to_layer(unknown_funcs.at(1), layer_0, D<0>{});
1165 
1166     Functions::two::physical_device::add_to_driver(unknown_funcs.at(2), physical_device);
1167     Functions::two::physical_device::add_to_layer(unknown_funcs.at(2), layer_1, D<1>{});
1168 
1169     Functions::three::physical_device::add_to_driver(unknown_funcs.at(3), physical_device);
1170     Functions::three::physical_device::add_to_layer(unknown_funcs.at(3), layer_0, D<2>{});
1171     Functions::three::physical_device::add_to_layer(unknown_funcs.at(3), layer_1, D<3>{});
1172 
1173     Functions::four::physical_device::add_implementation_to_layer(unknown_funcs.at(4), layer_0);
1174     Functions::four::physical_device::add_to_layer(unknown_funcs.at(4), layer_1, D<4>{});
1175 
1176     Functions::zero::physical_device::add_to_layer(unknown_funcs.at(5), layer_0, D<5>{});
1177     Functions::zero::physical_device::add_implementation_to_layer(unknown_funcs.at(5), layer_1);
1178 
1179     Functions::two::physical_device::add_to_driver(unknown_funcs.at(12), physical_device);
1180     Functions::zero::physical_device::add_to_layer(unknown_funcs.at(12), layer_0, D<12>{});
1181     Functions::zero::physical_device::add_implementation_to_layer(unknown_funcs.at(12), layer_1);
1182 
1183     // Device functions
1184     Functions::one::device::add_to_driver(unknown_funcs.at(6), physical_device);
1185 
1186     Functions::two::device::add_to_driver(unknown_funcs.at(7), physical_device);
1187     Functions::two::device::add_to_layer(unknown_funcs.at(7), layer_0, D<6>{});
1188 
1189     Functions::three::device::add_to_driver(unknown_funcs.at(8), physical_device);
1190     Functions::three::device::add_to_layer(unknown_funcs.at(8), layer_1, D<7>{});
1191 
1192     Functions::four::device::add_to_driver(unknown_funcs.at(9), physical_device);
1193     Functions::four::device::add_to_layer(unknown_funcs.at(9), layer_0, D<8>{});
1194     Functions::four::device::add_to_layer(unknown_funcs.at(9), layer_1, D<9>{});
1195 
1196     Functions::zero::device::add_implementation_to_layer(unknown_funcs.at(10), layer_0);
1197     Functions::zero::device::add_to_layer(unknown_funcs.at(10), layer_1, D<10>{});
1198 
1199     Functions::one::device::add_to_layer(unknown_funcs.at(11), layer_0, D<11>{});
1200     Functions::one::device::add_implementation_to_layer(unknown_funcs.at(11), layer_1);
1201 
1202     {
1203         InstWrapper inst{env.vulkan_functions};
1204         inst.CheckCreate();
1205 
1206         VkPhysicalDevice phys_dev = inst.GetPhysDev();
1207         DeviceWrapper dev{inst};
1208         dev.CheckCreate(phys_dev);
1209 
1210         unknown_funcs.at(0).check<Functions::zero::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
1211         unknown_funcs.at(1).check<Functions::one::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
1212         unknown_funcs.at(2).check<Functions::two::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
1213         unknown_funcs.at(3).check<Functions::three::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
1214         unknown_funcs.at(4).check<Functions::four::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
1215         unknown_funcs.at(5).check<Functions::zero::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
1216 
1217         // Check that GIPA works for device functions
1218         unknown_funcs.at(6).check<Functions::one::device>(env.vulkan_functions, inst.inst, dev.dev);
1219         unknown_funcs.at(7).check<Functions::two::device>(env.vulkan_functions, inst.inst, dev.dev);
1220         unknown_funcs.at(8).check<Functions::three::device>(env.vulkan_functions, inst.inst, dev.dev);
1221         unknown_funcs.at(9).check<Functions::four::device>(env.vulkan_functions, inst.inst, dev.dev);
1222         unknown_funcs.at(10).check<Functions::zero::device>(env.vulkan_functions, inst.inst, dev.dev);
1223         unknown_funcs.at(11).check<Functions::one::device>(env.vulkan_functions, inst.inst, dev.dev);
1224 
1225         // Check that GDPA works for device functions
1226         unknown_funcs.at(6).check<Functions::one::device>(env.vulkan_functions, dev.dev, dev.dev);
1227         unknown_funcs.at(7).check<Functions::two::device>(env.vulkan_functions, dev.dev, dev.dev);
1228         unknown_funcs.at(8).check<Functions::three::device>(env.vulkan_functions, dev.dev, dev.dev);
1229         unknown_funcs.at(9).check<Functions::four::device>(env.vulkan_functions, dev.dev, dev.dev);
1230         unknown_funcs.at(10).check<Functions::zero::device>(env.vulkan_functions, dev.dev, dev.dev);
1231         unknown_funcs.at(11).check<Functions::one::device>(env.vulkan_functions, dev.dev, dev.dev);
1232     }
1233 
1234     {
1235         InstWrapper inst{env.vulkan_functions};
1236         inst.CheckCreate();
1237 
1238         VkPhysicalDevice phys_dev = inst.GetPhysDev();
1239         DeviceWrapper dev{inst};
1240         dev.CheckCreate(phys_dev);
1241         // Load device functions first, to make sure order of function loading is not important
1242         // Check that GIPA works for device functions
1243         unknown_funcs.at(6).check<Functions::one::device>(env.vulkan_functions, inst.inst, dev.dev);
1244         unknown_funcs.at(7).check<Functions::two::device>(env.vulkan_functions, inst.inst, dev.dev);
1245         unknown_funcs.at(8).check<Functions::three::device>(env.vulkan_functions, inst.inst, dev.dev);
1246         unknown_funcs.at(9).check<Functions::four::device>(env.vulkan_functions, inst.inst, dev.dev);
1247         unknown_funcs.at(10).check<Functions::zero::device>(env.vulkan_functions, inst.inst, dev.dev);
1248         unknown_funcs.at(11).check<Functions::one::device>(env.vulkan_functions, inst.inst, dev.dev);
1249 
1250         // Check that GDPA works for device functions
1251         unknown_funcs.at(6).check<Functions::one::device>(env.vulkan_functions, dev.dev, dev.dev);
1252         unknown_funcs.at(7).check<Functions::two::device>(env.vulkan_functions, dev.dev, dev.dev);
1253         unknown_funcs.at(8).check<Functions::three::device>(env.vulkan_functions, dev.dev, dev.dev);
1254         unknown_funcs.at(9).check<Functions::four::device>(env.vulkan_functions, dev.dev, dev.dev);
1255         unknown_funcs.at(10).check<Functions::zero::device>(env.vulkan_functions, dev.dev, dev.dev);
1256         unknown_funcs.at(11).check<Functions::one::device>(env.vulkan_functions, dev.dev, dev.dev);
1257 
1258         unknown_funcs.at(0).check<Functions::zero::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
1259         unknown_funcs.at(1).check<Functions::one::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
1260         unknown_funcs.at(2).check<Functions::two::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
1261         unknown_funcs.at(3).check<Functions::three::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
1262         unknown_funcs.at(4).check<Functions::four::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
1263         unknown_funcs.at(5).check<Functions::zero::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
1264     }
1265 }
1266 
TEST(UnknownFunction, PhysicalDeviceFunctionInLayer)1267 TEST(UnknownFunction, PhysicalDeviceFunctionInLayer) {
1268     FrameworkEnvironment env{};
1269     env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
1270 
1271     env.add_implicit_layer(ManifestLayer{}
1272                                .add_layer(ManifestLayer::LayerDescription{}
1273                                               .set_name("VK_LAYER_implicit_layer_1")
1274                                               .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_0)
1275                                               .set_disable_environment("DISABLE_ME"))
1276                                .set_file_format_version({1, 0, 0}),
1277                            "implicit_layer_1.json");
1278 
1279     UnknownFunction unknown_func{"vkPhysicalDeviceFunctionInLayer"};
1280     const char* ext_name = "VK_EXT_not_funny";
1281 
1282     const char* explicit_layer_unknown_function_implement = "VK_LAYER_implement_unknown_function";
1283     env.add_explicit_layer(
1284         ManifestLayer{}
1285             .add_layer(ManifestLayer::LayerDescription{}
1286                            .set_name(explicit_layer_unknown_function_implement)
1287                            .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
1288                            .add_instance_extension(ManifestLayer::LayerDescription::Extension{ext_name, 0, {unknown_func.name}}))
1289             .set_file_format_version({1, 1, 0}),
1290         "implement_unknown_function.json");
1291     auto& layer0 = env.get_test_layer(1);
1292 
1293     const char* explicit_layer_to_enable_1 = "VK_LAYER_explicit_layer_1";
1294     env.add_explicit_layer(ManifestLayer{}
1295                                .add_layer(ManifestLayer::LayerDescription{}
1296                                               .set_name(explicit_layer_to_enable_1)
1297                                               .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2))
1298                                .set_file_format_version({1, 2, 0}),
1299                            "explicit_layer_2.json");
1300 
1301     Functions::four::physical_device::add_implementation_to_layer(unknown_func, layer0);
1302 
1303     InstWrapper inst{env.vulkan_functions};
1304     inst.create_info.add_layer(explicit_layer_to_enable_1);
1305     inst.create_info.add_layer(explicit_layer_unknown_function_implement);
1306     inst.CheckCreate();
1307 
1308     VkPhysicalDevice phys_dev = inst.GetPhysDev();
1309 
1310     unknown_func.check<Functions::four::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
1311 }
1312