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 31TEST(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 62TEST(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. 86TEST(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 181TEST(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 189TEST(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. 203TEST(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 303TEST(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 328TEST(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 382TEST(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 439TEST(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