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