1 /*
2 * Copyright (c) 2021-2022 The Khronos Group Inc.
3 * Copyright (c) 2021-2022 Valve Corporation
4 * Copyright (c) 2021-2022 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 // Verify that the various ways to get vkGetInstanceProcAddr return the same value
TEST(GetProcAddr, VerifyGetInstanceProcAddr)31 TEST(GetProcAddr, VerifyGetInstanceProcAddr) {
32 FrameworkEnvironment env{};
33 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device("physical_device_0");
34 {
35 InstWrapper inst{env.vulkan_functions};
36 inst.create_info.set_api_version(VK_API_VERSION_1_1);
37 inst.CheckCreate();
38
39 // NOTE: The vulkan_functions are queried using the platform get proc addr from the loader. So we'll compare
40 // that to what is returned by asking it what the various Vulkan get proc addr functions are.
41 PFN_vkGetInstanceProcAddr gipa_loader = env.vulkan_functions.vkGetInstanceProcAddr;
42 PFN_vkGetInstanceProcAddr gipa_queried = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
43 env.vulkan_functions.vkGetInstanceProcAddr(inst.inst, "vkGetInstanceProcAddr"));
44 ASSERT_EQ(gipa_loader, gipa_queried);
45 }
46
47 {
48 InstWrapper inst{env.vulkan_functions};
49 inst.create_info.set_api_version(VK_API_VERSION_1_3);
50 inst.CheckCreate();
51
52 // NOTE: The vulkan_functions are queried using the platform get proc addr from the loader. So we'll compare
53 // that to what is returned by asking it what the various Vulkan get proc addr functions are.
54 PFN_vkGetInstanceProcAddr gipa_loader = env.vulkan_functions.vkGetInstanceProcAddr;
55 PFN_vkGetInstanceProcAddr gipa_queried = reinterpret_cast<PFN_vkGetInstanceProcAddr>(
56 env.vulkan_functions.vkGetInstanceProcAddr(inst.inst, "vkGetInstanceProcAddr"));
57 ASSERT_EQ(gipa_loader, gipa_queried);
58 }
59 }
60
61 // Verify that the various ways to get vkGetDeviceProcAddr return the same value
TEST(GetProcAddr, VerifyGetDeviceProcAddr)62 TEST(GetProcAddr, VerifyGetDeviceProcAddr) {
63 FrameworkEnvironment env{};
64 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device("physical_device_0");
65
66 InstWrapper inst{env.vulkan_functions};
67 inst.create_info.set_api_version(VK_API_VERSION_1_1);
68 inst.CheckCreate();
69 VkPhysicalDevice phys_dev = inst.GetPhysDev();
70
71 // NOTE: The vulkan_functions are queried using the platform get proc addr from the loader. So we'll compare
72 // that to what is returned by asking it what the various Vulkan get proc addr functions are.
73 PFN_vkGetDeviceProcAddr gdpa_loader = env.vulkan_functions.vkGetDeviceProcAddr;
74 PFN_vkGetDeviceProcAddr gdpa_inst_queried = inst.load("vkGetDeviceProcAddr");
75 ASSERT_EQ(gdpa_loader, gdpa_inst_queried);
76
77 DeviceWrapper dev{inst};
78 dev.CheckCreate(phys_dev);
79
80 PFN_vkGetDeviceProcAddr gdpa_dev_queried = dev.load("vkGetDeviceProcAddr");
81 ASSERT_EQ(gdpa_loader, gdpa_dev_queried);
82 }
83
84 // Load the global function pointers with and without a NULL vkInstance handle.
85 // Call the function to make sure it is callable, don't care about what is returned.
TEST(GetProcAddr, GlobalFunctions)86 TEST(GetProcAddr, GlobalFunctions) {
87 FrameworkEnvironment env{};
88 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device("physical_device_0");
89
90 auto& gipa = env.vulkan_functions.vkGetInstanceProcAddr;
91 // global entry points with NULL instance handle
92 {
93 auto EnumerateInstanceExtensionProperties =
94 reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(gipa(NULL, "vkEnumerateInstanceExtensionProperties"));
95 handle_assert_has_value(EnumerateInstanceExtensionProperties);
96 uint32_t ext_count = 0;
97 ASSERT_EQ(VK_SUCCESS, EnumerateInstanceExtensionProperties("", &ext_count, nullptr));
98
99 auto EnumerateInstanceLayerProperties =
100 reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(gipa(NULL, "vkEnumerateInstanceLayerProperties"));
101 handle_assert_has_value(EnumerateInstanceLayerProperties);
102 uint32_t layer_count = 0;
103 ASSERT_EQ(VK_SUCCESS, EnumerateInstanceLayerProperties(&layer_count, nullptr));
104
105 auto EnumerateInstanceVersion = reinterpret_cast<PFN_vkEnumerateInstanceVersion>(gipa(NULL, "vkEnumerateInstanceVersion"));
106 handle_assert_has_value(EnumerateInstanceVersion);
107 uint32_t api_version = 0;
108 EnumerateInstanceVersion(&api_version);
109
110 auto GetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(gipa(NULL, "vkGetInstanceProcAddr"));
111 ASSERT_EQ(GetInstanceProcAddr,
112 reinterpret_cast<PFN_vkGetInstanceProcAddr>(GetInstanceProcAddr(NULL, "vkGetInstanceProcAddr")));
113
114 auto CreateInstance = reinterpret_cast<PFN_vkCreateInstance>(gipa(NULL, "vkCreateInstance"));
115 handle_assert_has_value(CreateInstance);
116 }
117 // Now create an instance and query the functions again - should work because the instance version is less than 1.2
118 for (int i = 0; i <= 2; i++) {
119 InstWrapper inst{env.vulkan_functions};
120 inst.create_info.api_version = VK_MAKE_API_VERSION(0, 1, i, 0);
121 inst.CheckCreate();
122
123 PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties =
124 inst.load("vkEnumerateInstanceExtensionProperties");
125 handle_assert_has_value(EnumerateInstanceExtensionProperties);
126 uint32_t ext_count = 0;
127 ASSERT_EQ(VK_SUCCESS, EnumerateInstanceExtensionProperties("", &ext_count, nullptr));
128
129 PFN_vkEnumerateInstanceLayerProperties EnumerateInstanceLayerProperties = inst.load("vkEnumerateInstanceLayerProperties");
130 handle_assert_has_value(EnumerateInstanceLayerProperties);
131 uint32_t layer_count = 0;
132 ASSERT_EQ(VK_SUCCESS, EnumerateInstanceLayerProperties(&layer_count, nullptr));
133
134 PFN_vkEnumerateInstanceVersion EnumerateInstanceVersion = inst.load("vkEnumerateInstanceVersion");
135 handle_assert_has_value(EnumerateInstanceVersion);
136 uint32_t api_version = 0;
137 EnumerateInstanceVersion(&api_version);
138
139 PFN_vkGetInstanceProcAddr GetInstanceProcAddr = inst.load("vkGetInstanceProcAddr");
140 handle_assert_has_value(GetInstanceProcAddr);
141 ASSERT_EQ(GetInstanceProcAddr,
142 reinterpret_cast<PFN_vkGetInstanceProcAddr>(GetInstanceProcAddr(inst, "vkGetInstanceProcAddr")));
143
144 PFN_vkCreateInstance CreateInstance = inst.load("vkCreateInstance");
145 handle_assert_has_value(CreateInstance);
146 }
147 {
148 // Create a 1.3 instance - now everything should return NULL
149 InstWrapper inst{env.vulkan_functions};
150 inst.create_info.api_version = VK_MAKE_API_VERSION(0, 1, 3, 0);
151 inst.CheckCreate();
152
153 PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties =
154 inst.load("vkEnumerateInstanceExtensionProperties");
155 handle_assert_null(EnumerateInstanceExtensionProperties);
156
157 PFN_vkEnumerateInstanceLayerProperties EnumerateInstanceLayerProperties = inst.load("vkEnumerateInstanceLayerProperties");
158 handle_assert_null(EnumerateInstanceLayerProperties);
159
160 PFN_vkEnumerateInstanceVersion EnumerateInstanceVersion = inst.load("vkEnumerateInstanceVersion");
161 handle_assert_null(EnumerateInstanceVersion);
162
163 PFN_vkCreateInstance CreateInstance = inst.load("vkCreateInstance");
164 handle_assert_null(CreateInstance);
165
166 PFN_vkGetInstanceProcAddr GetInstanceProcAddr = inst.load("vkGetInstanceProcAddr");
167 handle_assert_equal(env.vulkan_functions.vkGetInstanceProcAddr, GetInstanceProcAddr);
168 ASSERT_EQ(GetInstanceProcAddr,
169 reinterpret_cast<PFN_vkGetInstanceProcAddr>(GetInstanceProcAddr(inst, "vkGetInstanceProcAddr")));
170 ASSERT_EQ(GetInstanceProcAddr,
171 reinterpret_cast<PFN_vkGetInstanceProcAddr>(GetInstanceProcAddr(NULL, "vkGetInstanceProcAddr")));
172 // get a non pre-instance function pointer
173 PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices = inst.load("vkEnumeratePhysicalDevices");
174 handle_assert_has_value(EnumeratePhysicalDevices);
175
176 EnumeratePhysicalDevices = reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(gipa(NULL, "vkEnumeratePhysicalDevices"));
177 handle_assert_null(EnumeratePhysicalDevices);
178 }
179 }
180
TEST(GetProcAddr, Verify10FunctionsFailToLoadWithSingleDriver)181 TEST(GetProcAddr, Verify10FunctionsFailToLoadWithSingleDriver) {
182 FrameworkEnvironment env{};
183 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({}).set_can_query_GetPhysicalDeviceFuncs(false);
184
185 InstWrapper inst{env.vulkan_functions};
186 inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
187 }
188
TEST(GetProcAddr, Verify10FunctionsLoadWithMultipleDrivers)189 TEST(GetProcAddr, Verify10FunctionsLoadWithMultipleDrivers) {
190 FrameworkEnvironment env{};
191 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({});
192 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device({}).set_can_query_GetPhysicalDeviceFuncs(false);
193
194 InstWrapper inst{env.vulkan_functions};
195 inst.CheckCreate();
196
197 inst.GetPhysDevs(1);
198 }
199
200 // Swapchain functions which require a terminator in all cases have situations where the driver may have a
201 // NULL function pointer but the loader shouldn't abort() if that is the case. Rather, it should log a message
202 // and return VK_SUCCESS to maintain previous behavior.
TEST(GetDeviceProcAddr, SwapchainFuncsWithTerminator)203 TEST(GetDeviceProcAddr, SwapchainFuncsWithTerminator) {
204 FrameworkEnvironment env{};
205 auto& driver =
206 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).setup_WSI().add_physical_device("physical_device_0");
207
208 InstWrapper inst(env.vulkan_functions);
209 inst.create_info.add_extension("VK_EXT_debug_utils");
210 inst.create_info.setup_WSI();
211 ASSERT_NO_FATAL_FAILURE(inst.CheckCreate());
212
213 VkSurfaceKHR surface{};
214 ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
215
216 DebugUtilsWrapper log{inst};
217 ASSERT_EQ(VK_SUCCESS, CreateDebugUtilsMessenger(log));
218 auto phys_dev = inst.GetPhysDev();
219 {
220 DeviceWrapper dev{inst};
221 ASSERT_NO_FATAL_FAILURE(dev.CheckCreate(phys_dev));
222 DeviceFunctions dev_funcs{env.vulkan_functions, dev};
223
224 PFN_vkCreateSwapchainKHR CreateSwapchainKHR = dev.load("vkCreateSwapchainKHR");
225 PFN_vkCreateSwapchainKHR inst_CreateSwapchainKHR = inst.load("vkCreateSwapchainKHR");
226 PFN_vkGetDeviceGroupSurfacePresentModesKHR GetDeviceGroupSurfacePresentModesKHR =
227 dev.load("vkGetDeviceGroupSurfacePresentModesKHR");
228 PFN_vkCreateSharedSwapchainsKHR CreateSharedSwapchainsKHR = dev.load("vkCreateSharedSwapchainsKHR");
229 ASSERT_FALSE(CreateSwapchainKHR);
230 ASSERT_TRUE(inst_CreateSwapchainKHR);
231 ASSERT_FALSE(GetDeviceGroupSurfacePresentModesKHR);
232 ASSERT_FALSE(CreateSharedSwapchainsKHR);
233
234 VkSwapchainCreateInfoKHR info{};
235 info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
236 info.surface = surface;
237
238 VkSwapchainKHR swapchain{};
239 if (CreateSwapchainKHR) CreateSwapchainKHR(dev.dev, &info, nullptr, &swapchain);
240 ASSERT_FALSE(
241 log.find("vkCreateSwapchainKHR: Driver's function pointer was NULL, returning VK_SUCCESS. Was the VK_KHR_swapchain "
242 "extension enabled?"));
243 log.logger.clear();
244 if (dev_funcs.vkDestroySwapchainKHR) dev_funcs.vkDestroySwapchainKHR(dev.dev, swapchain, nullptr);
245 // try to call the vkCreateSwapchainKHR acquired from the instance - this *should* abort due to not enabling the extension
246 if (inst_CreateSwapchainKHR) {
247 ASSERT_DEATH(inst_CreateSwapchainKHR(dev.dev, &info, nullptr, &swapchain),
248 "vkCreateSwapchainKHR: Driver's function pointer was NULL, returning VK_SUCCESS. Was the VK_KHR_swapchain "
249 "extension enabled?");
250 }
251 log.logger.clear();
252 if (dev_funcs.vkDestroySwapchainKHR) dev_funcs.vkDestroySwapchainKHR(dev.dev, swapchain, nullptr);
253
254 VkDeviceGroupPresentModeFlagsKHR modes{};
255 if (GetDeviceGroupSurfacePresentModesKHR) GetDeviceGroupSurfacePresentModesKHR(dev.dev, surface, &modes);
256
257 if (CreateSharedSwapchainsKHR) CreateSharedSwapchainsKHR(dev.dev, 1, &info, nullptr, &swapchain);
258 }
259 driver.physical_devices.at(0).add_extensions({"VK_KHR_swapchain", "VK_KHR_display_swapchain", "VK_EXT_debug_marker"});
260 {
261 DeviceWrapper dev{inst};
262 dev.create_info.add_extensions({"VK_KHR_swapchain", "VK_KHR_display_swapchain", "VK_EXT_debug_marker"});
263 ASSERT_NO_FATAL_FAILURE(dev.CheckCreate(phys_dev));
264 DeviceFunctions dev_funcs{env.vulkan_functions, dev};
265
266 PFN_vkCreateSwapchainKHR CreateSwapchainKHR = dev.load("vkCreateSwapchainKHR");
267 PFN_vkCreateSwapchainKHR inst_CreateSwapchainKHR = inst.load("vkCreateSwapchainKHR");
268 PFN_vkGetDeviceGroupSurfacePresentModesKHR GetDeviceGroupSurfacePresentModesKHR =
269 dev.load("vkGetDeviceGroupSurfacePresentModesKHR");
270 PFN_vkCreateSharedSwapchainsKHR CreateSharedSwapchainsKHR = dev.load("vkCreateSharedSwapchainsKHR");
271 ASSERT_TRUE(CreateSwapchainKHR);
272 ASSERT_TRUE(inst_CreateSwapchainKHR);
273 ASSERT_TRUE(GetDeviceGroupSurfacePresentModesKHR);
274 ASSERT_TRUE(CreateSharedSwapchainsKHR);
275
276 VkSwapchainCreateInfoKHR info{};
277 info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
278 info.surface = surface;
279
280 VkSwapchainKHR swapchain{};
281 if (CreateSwapchainKHR) CreateSwapchainKHR(dev.dev, &info, nullptr, &swapchain);
282 ASSERT_FALSE(
283 log.find("vkCreateSwapchainKHR: Driver's function pointer was NULL, returning VK_SUCCESS. Was the VK_KHR_swapchain "
284 "extension enabled?"));
285 log.logger.clear();
286 if (dev_funcs.vkDestroySwapchainKHR) dev_funcs.vkDestroySwapchainKHR(dev.dev, swapchain, nullptr);
287 if (inst_CreateSwapchainKHR) inst_CreateSwapchainKHR(dev.dev, &info, nullptr, &swapchain);
288 ASSERT_FALSE(
289 log.find("vkCreateSwapchainKHR: Driver's function pointer was NULL, returning VK_SUCCESS. Was the VK_KHR_swapchain "
290 "extension enabled?"));
291 log.logger.clear();
292 if (dev_funcs.vkDestroySwapchainKHR) dev_funcs.vkDestroySwapchainKHR(dev.dev, swapchain, nullptr);
293
294 VkDeviceGroupPresentModeFlagsKHR modes{};
295 if (GetDeviceGroupSurfacePresentModesKHR) GetDeviceGroupSurfacePresentModesKHR(dev.dev, surface, &modes);
296
297 if (CreateSharedSwapchainsKHR) CreateSharedSwapchainsKHR(dev.dev, 1, &info, nullptr, &swapchain);
298 }
299 env.vulkan_functions.vkDestroySurfaceKHR(inst.inst, surface, nullptr);
300 }
301
302 // Verify that the various ways to get vkGetDeviceProcAddr return the same value
TEST(GetProcAddr, PreserveLayerGettingVkCreateDeviceWithNullInstance)303 TEST(GetProcAddr, PreserveLayerGettingVkCreateDeviceWithNullInstance) {
304 FrameworkEnvironment env{};
305 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device("physical_device_0");
306
307 env.add_implicit_layer(TestLayerDetails(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
308 .set_name("VK_LAYER_technically_buggy_layer")
309 .set_description("actually_layer_1")
310 .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
311 .set_disable_environment("if_you_can")),
312 "buggy_layer_1.json"));
313 env.get_test_layer().set_buggy_query_of_vkCreateDevice(true);
314 InstWrapper inst{env.vulkan_functions};
315 inst.create_info.set_api_version(VK_API_VERSION_1_1);
316 inst.CheckCreate();
317 VkPhysicalDevice phys_dev = inst.GetPhysDev();
318
319 DeviceWrapper dev{inst};
320 dev.CheckCreate(phys_dev);
321 }
322
323 // The following tests - AppQueries11FunctionsWhileOnlyEnabling10, AppQueries12FunctionsWhileOnlyEnabling11, and
324 // AppQueries13FunctionsWhileOnlyEnabling12 - check that vkGetDeviceProcAddr only returning functions from core versions up to
325 // the apiVersion declared in VkApplicationInfo. Function querying should succeed if VK_KHR_maintenance_5 is not enabled, and they
326 // should return zero when that extension is enabled.
327
TEST(GetDeviceProcAddr, AppQueries11FunctionsWhileOnlyEnabling10)328 TEST(GetDeviceProcAddr, AppQueries11FunctionsWhileOnlyEnabling10) {
329 FrameworkEnvironment env{};
330 auto& driver =
331 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
332 .set_icd_api_version(VK_API_VERSION_1_1)
333 .add_physical_device(
334 PhysicalDevice{}.set_api_version(VK_API_VERSION_1_1).add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME).finish());
335
336 std::vector<const char*> functions = {"vkGetDeviceQueue2", "vkCmdDispatchBase", "vkCreateDescriptorUpdateTemplate"};
337 for (const auto& f : functions) {
338 driver.physical_devices.back().add_device_function(VulkanFunction{f, [] {}});
339 }
340 { // doesn't enable the feature or extension
341 InstWrapper inst{env.vulkan_functions};
342 inst.create_info.set_api_version(1, 0, 0);
343 inst.CheckCreate();
344
345 DeviceWrapper dev{inst};
346 dev.CheckCreate(inst.GetPhysDev());
347 for (const auto& f : functions) {
348 ASSERT_NE(nullptr, dev->vkGetDeviceProcAddr(dev.dev, f));
349 }
350 }
351 { // doesn't enable the feature
352 InstWrapper inst{env.vulkan_functions};
353 inst.create_info.set_api_version(1, 0, 0);
354 inst.CheckCreate();
355
356 DeviceWrapper dev{inst};
357 dev.create_info.add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
358 dev.CheckCreate(inst.GetPhysDev());
359 for (const auto& f : functions) {
360 ASSERT_NE(nullptr, dev->vkGetDeviceProcAddr(dev.dev, f));
361 }
362 }
363 { // enables the feature and extension
364 InstWrapper inst{env.vulkan_functions};
365 inst.create_info.set_api_version(1, 0, 0);
366 inst.CheckCreate();
367
368 VkPhysicalDeviceMaintenance5FeaturesKHR features{};
369 features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR;
370 features.maintenance5 = VK_TRUE;
371
372 DeviceWrapper dev{inst};
373 dev.create_info.add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
374 dev.create_info.dev.pNext = &features;
375 dev.CheckCreate(inst.GetPhysDev());
376 for (const auto& f : functions) {
377 ASSERT_EQ(nullptr, dev->vkGetDeviceProcAddr(dev.dev, f));
378 }
379 }
380 }
381
TEST(GetDeviceProcAddr, AppQueries12FunctionsWhileOnlyEnabling11)382 TEST(GetDeviceProcAddr, AppQueries12FunctionsWhileOnlyEnabling11) {
383 FrameworkEnvironment env{};
384 auto& driver =
385 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_2))
386 .set_icd_api_version(VK_API_VERSION_1_2)
387 .add_physical_device(
388 PhysicalDevice{}.set_api_version(VK_API_VERSION_1_2).add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME).finish());
389 std::vector<const char*> functions = {"vkCmdDrawIndirectCount", "vkCmdNextSubpass2", "vkGetBufferDeviceAddress",
390 "vkGetDeviceMemoryOpaqueCaptureAddress"};
391 for (const auto& f : functions) {
392 driver.physical_devices.back().add_device_function(VulkanFunction{f, [] {}});
393 }
394 { // doesn't enable the feature or extension
395 InstWrapper inst{env.vulkan_functions};
396 inst.create_info.set_api_version(1, 1, 0);
397 inst.CheckCreate();
398
399 DeviceWrapper dev{inst};
400 dev.CheckCreate(inst.GetPhysDev());
401
402 for (const auto& f : functions) {
403 ASSERT_NE(nullptr, dev->vkGetDeviceProcAddr(dev.dev, f));
404 }
405 }
406 { // doesn't enable the feature
407 InstWrapper inst{env.vulkan_functions};
408 inst.create_info.set_api_version(1, 1, 0);
409 inst.CheckCreate();
410
411 DeviceWrapper dev{inst};
412 dev.create_info.add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
413 dev.CheckCreate(inst.GetPhysDev());
414
415 for (const auto& f : functions) {
416 ASSERT_NE(nullptr, dev->vkGetDeviceProcAddr(dev.dev, f));
417 }
418 }
419 { // enables the feature and extension
420 InstWrapper inst{env.vulkan_functions};
421 inst.create_info.set_api_version(1, 1, 0);
422 inst.CheckCreate();
423
424 VkPhysicalDeviceMaintenance5FeaturesKHR features{};
425 features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR;
426 features.maintenance5 = VK_TRUE;
427
428 DeviceWrapper dev{inst};
429 dev.create_info.add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
430 dev.create_info.dev.pNext = &features;
431 dev.CheckCreate(inst.GetPhysDev());
432
433 for (const auto& f : functions) {
434 ASSERT_EQ(nullptr, dev->vkGetDeviceProcAddr(dev.dev, f));
435 }
436 }
437 }
438
TEST(GetDeviceProcAddr, AppQueries13FunctionsWhileOnlyEnabling12)439 TEST(GetDeviceProcAddr, AppQueries13FunctionsWhileOnlyEnabling12) {
440 FrameworkEnvironment env{};
441 auto& driver =
442 env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_3))
443 .set_icd_api_version(VK_API_VERSION_1_3)
444 .add_physical_device(
445 PhysicalDevice{}.set_api_version(VK_API_VERSION_1_3).add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME).finish());
446 std::vector<const char*> functions = {"vkCreatePrivateDataSlot", "vkGetDeviceBufferMemoryRequirements", "vkCmdWaitEvents2",
447 "vkGetDeviceImageSparseMemoryRequirements"};
448
449 for (const auto& f : functions) {
450 driver.physical_devices.back().add_device_function(VulkanFunction{f, [] {}});
451 }
452 { // doesn't enable the feature or extension
453 InstWrapper inst{env.vulkan_functions};
454 inst.create_info.set_api_version(1, 2, 0);
455 inst.CheckCreate();
456
457 DeviceWrapper dev{inst};
458 dev.CheckCreate(inst.GetPhysDev());
459
460 for (const auto& f : functions) {
461 ASSERT_NE(nullptr, dev->vkGetDeviceProcAddr(dev.dev, f));
462 }
463 }
464 { // doesn't enable the feature
465 InstWrapper inst{env.vulkan_functions};
466 inst.create_info.set_api_version(1, 2, 0);
467 inst.CheckCreate();
468
469 DeviceWrapper dev{inst};
470 dev.create_info.add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
471 dev.CheckCreate(inst.GetPhysDev());
472
473 for (const auto& f : functions) {
474 ASSERT_NE(nullptr, dev->vkGetDeviceProcAddr(dev.dev, f));
475 }
476 }
477 { // enables the feature and extension
478 InstWrapper inst{env.vulkan_functions};
479 inst.create_info.set_api_version(1, 2, 0);
480 inst.CheckCreate();
481
482 VkPhysicalDeviceMaintenance5FeaturesKHR features{};
483 features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_FEATURES_KHR;
484 features.maintenance5 = VK_TRUE;
485
486 DeviceWrapper dev{inst};
487 dev.create_info.add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
488 dev.create_info.dev.pNext = &features;
489 dev.CheckCreate(inst.GetPhysDev());
490
491 for (const auto& f : functions) {
492 ASSERT_EQ(nullptr, dev->vkGetDeviceProcAddr(dev.dev, f));
493 }
494 }
495 }
496