From: Charles Giessen Date: Thu, 2 May 2024 16:53:19 +0000 (-0500) Subject: Allow layers to call global functions in vkCreateInstance X-Git-Tag: upstream/1.3.296~66 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e99fce9366ceabe1a1568d2d0febfaa39af1b065;p=platform%2Fupstream%2FVulkan-Loader.git Allow layers to call global functions in vkCreateInstance Layers that want to call other global functions during vkCreateInstance couldn't due to loader_gpa_instance_terminator missing the necessary logic. Because those global functions have a different signature, it was decided to update the terminator_ signatures to match the Vulkan API, and make dedicated pre-instance intercetpion functions with the appropriate Chain object as the first parameter. Now during the call down to vkCreateInstance a layer can query for pre-instance functions with vkGetInstanceProcAddr and is able to call them using the Vulkan API function signature. --- diff --git a/loader/generated/vk_loader_extensions.h b/loader/generated/vk_loader_extensions.h index 66fd83e5..d8104914 100644 --- a/loader/generated/vk_loader_extensions.h +++ b/loader/generated/vk_loader_extensions.h @@ -131,6 +131,10 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDevice( const VkAllocationCallbacks* pAllocator, VkDevice* pDevice); VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceExtensionProperties( + const char* pLayerName, + uint32_t* pPropertyCount, + VkExtensionProperties* pProperties); +VKAPI_ATTR VkResult VKAPI_CALL terminator_pre_instance_EnumerateInstanceExtensionProperties( const VkEnumerateInstanceExtensionPropertiesChain* chain, const char* pLayerName, uint32_t* pPropertyCount, @@ -141,6 +145,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties( uint32_t* pPropertyCount, VkExtensionProperties* pProperties); VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceLayerProperties( + uint32_t* pPropertyCount, + VkLayerProperties* pProperties); +VKAPI_ATTR VkResult VKAPI_CALL terminator_pre_instance_EnumerateInstanceLayerProperties( const VkEnumerateInstanceLayerPropertiesChain* chain, uint32_t* pPropertyCount, VkLayerProperties* pProperties); @@ -158,6 +165,8 @@ VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceSparseImageFormatProperti uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties); VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceVersion( + uint32_t* pApiVersion); +VKAPI_ATTR VkResult VKAPI_CALL terminator_pre_instance_EnumerateInstanceVersion( const VkEnumerateInstanceVersionChain* chain, uint32_t* pApiVersion); VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDeviceGroups( diff --git a/loader/loader.c b/loader/loader.c index a2cef49f..3058b365 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -4051,6 +4051,17 @@ VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL loader_gpa_instance_terminator(VkInstan if (!strcmp(pName, "vkCreateInstance")) { return (PFN_vkVoidFunction)terminator_CreateInstance; } + // If a layer is querying pre-instance functions using vkGetInstanceProcAddr, we need to return function pointers that match the + // Vulkan API + if (!strcmp(pName, "vkEnumerateInstanceLayerProperties")) { + return (PFN_vkVoidFunction)terminator_EnumerateInstanceLayerProperties; + } + if (!strcmp(pName, "vkEnumerateInstanceExtensionProperties")) { + return (PFN_vkVoidFunction)terminator_EnumerateInstanceExtensionProperties; + } + if (!strcmp(pName, "vkEnumerateInstanceVersion")) { + return (PFN_vkVoidFunction)terminator_EnumerateInstanceVersion; + } // While the spec is very clear that querying vkCreateDevice requires a valid VkInstance, because the loader allowed querying // with a NULL VkInstance handle for a long enough time, it is impractical to fix this bug in the loader @@ -6772,19 +6783,21 @@ VkStringErrorFlags vk_string_validate(const int max_length, const char *utf8) { return result; } -VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceVersion(const VkEnumerateInstanceVersionChain *chain, - uint32_t *pApiVersion) { - (void)chain; +VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceVersion(uint32_t *pApiVersion) { // NOTE: The Vulkan WG doesn't want us checking pApiVersion for NULL, but instead // prefers us crashing. *pApiVersion = VK_HEADER_VERSION_COMPLETE; return VK_SUCCESS; } -VKAPI_ATTR VkResult VKAPI_CALL -terminator_EnumerateInstanceExtensionProperties(const VkEnumerateInstanceExtensionPropertiesChain *chain, const char *pLayerName, - uint32_t *pPropertyCount, VkExtensionProperties *pProperties) { +VKAPI_ATTR VkResult VKAPI_CALL terminator_pre_instance_EnumerateInstanceVersion(const VkEnumerateInstanceVersionChain *chain, + uint32_t *pApiVersion) { (void)chain; + return terminator_EnumerateInstanceVersion(pApiVersion); +} + +VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pPropertyCount, + VkExtensionProperties *pProperties) { struct loader_extension_list *global_ext_list = NULL; struct loader_layer_list instance_layers; struct loader_extension_list local_ext_list; @@ -6879,10 +6892,15 @@ out: return res; } -VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceLayerProperties(const VkEnumerateInstanceLayerPropertiesChain *chain, - uint32_t *pPropertyCount, - VkLayerProperties *pProperties) { +VKAPI_ATTR VkResult VKAPI_CALL terminator_pre_instance_EnumerateInstanceExtensionProperties( + const VkEnumerateInstanceExtensionPropertiesChain *chain, const char *pLayerName, uint32_t *pPropertyCount, + VkExtensionProperties *pProperties) { (void)chain; + return terminator_EnumerateInstanceExtensionProperties(pLayerName, pPropertyCount, pProperties); +} + +VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount, + VkLayerProperties *pProperties) { VkResult result = VK_SUCCESS; struct loader_layer_list instance_layer_list; struct loader_envvar_all_filters layer_filters = {0}; @@ -6939,6 +6957,12 @@ out: return result; } +VKAPI_ATTR VkResult VKAPI_CALL terminator_pre_instance_EnumerateInstanceLayerProperties( + const VkEnumerateInstanceLayerPropertiesChain *chain, uint32_t *pPropertyCount, VkLayerProperties *pProperties) { + (void)chain; + return terminator_EnumerateInstanceLayerProperties(pPropertyCount, pProperties); +} + // ---- Vulkan Core 1.1 terminators VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDeviceGroups( diff --git a/loader/trampoline.c b/loader/trampoline.c index 14766b88..fec36d89 100644 --- a/loader/trampoline.c +++ b/loader/trampoline.c @@ -177,7 +177,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionPropert .version = VK_CURRENT_CHAIN_VERSION, .size = sizeof(chain_tail), }, - .pfnNextLayer = &terminator_EnumerateInstanceExtensionProperties, + .pfnNextLayer = &terminator_pre_instance_EnumerateInstanceExtensionProperties, .pNextLink = NULL, }; VkEnumerateInstanceExtensionPropertiesChain *chain_head = &chain_tail; @@ -283,7 +283,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties( .version = VK_CURRENT_CHAIN_VERSION, .size = sizeof(chain_tail), }, - .pfnNextLayer = &terminator_EnumerateInstanceLayerProperties, + .pfnNextLayer = &terminator_pre_instance_EnumerateInstanceLayerProperties, .pNextLink = NULL, }; VkEnumerateInstanceLayerPropertiesChain *chain_head = &chain_tail; @@ -396,7 +396,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceVersion(uint32_t .version = VK_CURRENT_CHAIN_VERSION, .size = sizeof(chain_tail), }, - .pfnNextLayer = &terminator_EnumerateInstanceVersion, + .pfnNextLayer = &terminator_pre_instance_EnumerateInstanceVersion, .pNextLink = NULL, }; VkEnumerateInstanceVersionChain *chain_head = &chain_tail; diff --git a/scripts/loader_extension_generator.py b/scripts/loader_extension_generator.py index 58413042..1df98f40 100644 --- a/scripts/loader_extension_generator.py +++ b/scripts/loader_extension_generator.py @@ -799,15 +799,21 @@ class LoaderExtensionOutputGenerator(OutputGenerator): mod_string = new_terminator.replace("VKAPI_CALL vk", "VKAPI_CALL terminator_") if cur_cmd.name in PRE_INSTANCE_FUNCTIONS: + pre_instance_basic_version = mod_string + mod_string = mod_string.replace("terminator_", "terminator_pre_instance_") mod_string = mod_string.replace(cur_cmd.name[2:] + '(\n', cur_cmd.name[2:] + '(\n const Vk' + cur_cmd.name[2:] + 'Chain* chain,\n') - if (cur_cmd.protect is not None): + if cur_cmd.protect is not None: terminators += '#if defined(%s)\n' % cur_cmd.protect + if cur_cmd.name in PRE_INSTANCE_FUNCTIONS: + terminators += pre_instance_basic_version + terminators += '\n' + terminators += mod_string terminators += '\n' - if (cur_cmd.protect is not None): + if cur_cmd.protect is not None: terminators += '#endif // %s\n' % cur_cmd.protect terminators += '\n' diff --git a/tests/framework/layer/test_layer.cpp b/tests/framework/layer/test_layer.cpp index 4fca974d..93c27c73 100644 --- a/tests/framework/layer/test_layer.cpp +++ b/tests/framework/layer/test_layer.cpp @@ -280,6 +280,37 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateInstance(const VkInstanceCreateInfo* if (layer.clobber_pInstance) { memset(*pInstance, 0, 128); } + PFN_vkEnumerateInstanceLayerProperties fpEnumerateInstanceLayerProperties{}; + PFN_vkEnumerateInstanceExtensionProperties fpEnumerateInstanceExtensionProperties{}; + PFN_vkEnumerateInstanceVersion fpEnumerateInstanceVersion{}; + + if (layer.query_vkEnumerateInstanceLayerProperties) { + fpEnumerateInstanceLayerProperties = reinterpret_cast( + fpGetInstanceProcAddr(nullptr, "vkEnumerateInstanceLayerProperties")); + uint32_t count = 0; + fpEnumerateInstanceLayerProperties(&count, nullptr); + if (count == 0) return VK_ERROR_LAYER_NOT_PRESENT; + std::vector layers{count, VkLayerProperties{}}; + fpEnumerateInstanceLayerProperties(&count, layers.data()); + if (count == 0) return VK_ERROR_LAYER_NOT_PRESENT; + } + if (layer.query_vkEnumerateInstanceExtensionProperties) { + fpEnumerateInstanceExtensionProperties = reinterpret_cast( + fpGetInstanceProcAddr(nullptr, "vkEnumerateInstanceExtensionProperties")); + uint32_t count = 0; + fpEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); + if (count == 0) return VK_ERROR_LAYER_NOT_PRESENT; + std::vector extensions{count, VkExtensionProperties{}}; + fpEnumerateInstanceExtensionProperties(nullptr, &count, extensions.data()); + if (count == 0) return VK_ERROR_LAYER_NOT_PRESENT; + } + if (layer.query_vkEnumerateInstanceVersion) { + fpEnumerateInstanceVersion = + reinterpret_cast(fpGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion")); + uint32_t version = 0; + fpEnumerateInstanceVersion(&version); + if (version == 0) return VK_ERROR_LAYER_NOT_PRESENT; + } // Continue call down the chain VkResult result = fpCreateInstance(create_info_pointer, pAllocator, pInstance); diff --git a/tests/framework/layer/test_layer.h b/tests/framework/layer/test_layer.h index d6d086c1..322bf9e0 100644 --- a/tests/framework/layer/test_layer.h +++ b/tests/framework/layer/test_layer.h @@ -195,6 +195,10 @@ struct TestLayer { // Clober the data pointed to by pDevice to overwrite the magic value BUILDER_VALUE(TestLayer, bool, clobber_pDevice, false) + BUILDER_VALUE(TestLayer, bool, query_vkEnumerateInstanceLayerProperties, false) + BUILDER_VALUE(TestLayer, bool, query_vkEnumerateInstanceExtensionProperties, false) + BUILDER_VALUE(TestLayer, bool, query_vkEnumerateInstanceVersion, false) + PFN_vkGetInstanceProcAddr next_vkGetInstanceProcAddr = VK_NULL_HANDLE; PFN_GetPhysicalDeviceProcAddr next_GetPhysicalDeviceProcAddr = VK_NULL_HANDLE; PFN_vkGetDeviceProcAddr next_vkGetDeviceProcAddr = VK_NULL_HANDLE; diff --git a/tests/loader_layer_tests.cpp b/tests/loader_layer_tests.cpp index 01ead76e..762865e4 100644 --- a/tests/loader_layer_tests.cpp +++ b/tests/loader_layer_tests.cpp @@ -2011,6 +2011,29 @@ TEST(ExplicitLayers, ContainsPreInstanceFunctions) { ASSERT_TRUE(string_eq(layers.at(0).layerName, explicit_layer_name)); } +TEST(ExplicitLayers, CallsPreInstanceFunctionsInCreateInstance) { + FrameworkEnvironment env; + env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({}); + const char* explicit_layer_name = "VK_LAYER_enabled_by_override"; + + env.add_explicit_layer( + ManifestLayer{}.set_file_format_version({1, 1, 2}).add_layer( + ManifestLayer::LayerDescription{}.set_name(explicit_layer_name).set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)), + "explicit_test_layer.json"); + + auto& layer = env.get_test_layer(0); + layer.set_query_vkEnumerateInstanceLayerProperties(true); + layer.set_query_vkEnumerateInstanceExtensionProperties(true); + layer.set_query_vkEnumerateInstanceVersion(true); + + InstWrapper inst{env.vulkan_functions}; + inst.create_info.add_layer(explicit_layer_name); + inst.CheckCreate(); + + auto layers = inst.GetActiveLayers(inst.GetPhysDev(), 1); + ASSERT_TRUE(string_eq(layers.at(0).layerName, explicit_layer_name)); +} + // This test makes sure that any layer calling GetPhysicalDeviceProperties2 inside of CreateInstance // succeeds and doesn't crash. TEST(LayerCreateInstance, GetPhysicalDeviceProperties2) {