diff --git a/library/TUTORIAL.md b/library/TUTORIAL.md index 3c127b09..cba98317 100644 --- a/library/TUTORIAL.md +++ b/library/TUTORIAL.md @@ -22,6 +22,8 @@ - [API reference](#api-reference) - [Preprocessor definitions](#preprocessor-definitions) - [Profile support and usage](#profile-support-and-usage) + - [Initializing capabilities](#initializing-capabilities) + - [Loading instance-level functions](#loading-instance-level-functions) - [Checking instance level support](#checking-instance-level-support) - [Creating instance with profile](#creating-instance-with-profile) - [Checking device level support](#checking-device-level-support) @@ -87,14 +89,21 @@ In order to use the Profiles API library, the application first has to create a ```C++ VpCapabilities capabilities = VK_NULL_HANDLE; - VpCapabilitiesCreateInfo createInfo; - createInfo.apiVersion = VK_API_VERSION_1_1; - createInfo.flags = VP_PROFILE_CREATE_STATIC_BIT; + vpCreateCapabilities(nullptr, &capabilities); +``` + +`vpCreateCapabilities` only allocates the `VpCapabilities` object; it no longer takes a `VpCapabilitiesCreateInfo` argument. The object must then be initialized with the global-level Vulkan functions (such as `vkCreateInstance` and `vkEnumerateInstanceExtensionProperties`) it needs by calling `vpInitialize`: + +```C++ + VpCapabilitiesCreateInfo createInfo{}; + createInfo.flags = VP_CAPABILITIES_CREATE_STATIC_BIT; createInfo.pVulkanFunctions = nullptr; - vpCreateCapabilities(&createInfo, nullptr, &capabilities); + vpInitialize(capabilities, &createInfo); ``` +`VP_CAPABILITIES_CREATE_STATIC_BIT` tells the library to resolve the Vulkan functions it needs from the statically linked Vulkan loader; this flag is only available when the application links against the Vulkan loader directly (i.e. `VK_NO_PROTOTYPES` and `VP_DISABLE_STATIC_LINKING` are not defined). Applications that load Vulkan dynamically should instead use `VP_CAPABILITIES_CREATE_DYNAMIC_BIT` and provide a `VpVulkanFunctions::GetInstanceProcAddr` pointer through `pVulkanFunctions`, from which the library will resolve the remaining global-level functions it needs. + Then the application has to make sure that the Vulkan implementation supports the selected profile as follows: ```C++ VkResult result = VK_SUCCESS; @@ -146,7 +155,17 @@ The above code example will create a Vulkan instance with the API version and in Make sure to set the `apiVersion` in the `VkApplicationInfo` structure at least to the minimum API version required by the profile, as seen above, to ensure the correct Vulkan API version is used. -Once a Vulkan instance is created, the application can check whether individual physical devices support the selected profile as follows: +Once a Vulkan instance is created, the `VpCapabilities` object must be told about it so that it can resolve the instance-level Vulkan functions (such as `vkCreateDevice` and `vkGetPhysicalDeviceFeatures2`) it needs for device-level queries and device creation: + +```C++ + result = vpLoadInstance(capabilities, instance, {}); + if (result != VK_SUCCESS) { + // something went wrong + ... + } +``` + +Once the instance-level functions are loaded, the application can check whether individual physical devices support the selected profile as follows: ```C++ result = vpGetPhysicalDeviceProfileSupport(capabilities, instance, physicalDevice, @@ -264,6 +283,96 @@ Where: The Vulkan Profile library offers a set of APIs to verify support for a particular Vulkan profile and to create Vulkan instances and devices using the extensions and features required by the profile. +#### Initializing capabilities + +After a `VpCapabilities` object is allocated with `vpCreateCapabilities`, it must be initialized with the global-level Vulkan functions it needs by calling the following command: + +```C++ +VkResult vpInitialize( + VpCapabilities capabilities, + const VpCapabilitiesCreateInfo* pCreateInfo); +``` + +Where: +* `capabilities` must be one of the capabilities handles returned from a call to `vpCreateCapabilities`. +* `pCreateInfo` is a pointer to the `VpCapabilitiesCreateInfo` structure specifying how the library should resolve the Vulkan functions it needs. + +The `VpCapabilitiesCreateInfo` structure is defined as follows: + +```C++ +typedef struct VpCapabilitiesCreateInfo +{ + VpCapabilitiesCreateFlags flags; + const VpVulkanFunctions* pVulkanFunctions; +} VpCapabilitiesCreateInfo; +``` + +Where: +* `flags` is a bitmask of `VpCapabilitiesCreateFlagBits` indicating how the Vulkan functions are to be resolved. +* `pVulkanFunctions` is either `NULL` or a pointer to a `VpVulkanFunctions` structure providing application-supplied Vulkan function pointers, as described below. + +The `VpCapabilitiesCreateFlagBits` enumeration is defined as follows: + +```C++ +typedef enum VpCapabilitiesCreateFlagBits { + VP_CAPABILITIES_CREATE_STATIC_BIT = (1 << 0), + VP_CAPABILITIES_CREATE_DYNAMIC_BIT = (1 << 1), + VP_CAPABILITIES_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VpCapabilitiesCreateFlagBits; +``` + +If `VP_CAPABILITIES_CREATE_STATIC_BIT` is specified, the library resolves the Vulkan functions it needs from the statically linked Vulkan loader. This flag is only available when `VK_NO_PROTOTYPES` and `VP_DISABLE_STATIC_LINKING` are not defined. + +If `VP_CAPABILITIES_CREATE_DYNAMIC_BIT` is specified, the application must provide a `VpVulkanFunctions::GetInstanceProcAddr` pointer through `pVulkanFunctions`, and the library resolves the remaining global-level functions it needs by calling it. + +The `VpVulkanFunctions` structure allows the application to explicitly provide any of the Vulkan function pointers the library needs (overriding or supplementing the ones resolved automatically): + +```C++ +typedef struct VpVulkanFunctions { + PFN_vkGetInstanceProcAddr GetInstanceProcAddr; + PFN_vkEnumerateInstanceVersion EnumerateInstanceVersion; + PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties; + PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties; + PFN_vkGetPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2; + PFN_vkGetPhysicalDeviceProperties2 GetPhysicalDeviceProperties2; + PFN_vkGetPhysicalDeviceFormatProperties2 GetPhysicalDeviceFormatProperties2; + PFN_vkGetPhysicalDeviceQueueFamilyProperties2 GetPhysicalDeviceQueueFamilyProperties2; + PFN_vkCreateInstance CreateInstance; + PFN_vkCreateDevice CreateDevice; +} VpVulkanFunctions; +``` + +Note that `VpVulkanFunctions` no longer includes a `GetDeviceProcAddr` member, as device-level functions are now resolved through the instance rather than through a device proc addr loader. + +#### Loading instance-level functions + +Once a Vulkan instance has been created, the instance-level Vulkan functions the library needs for device-level queries and device creation (such as `vkCreateDevice` and `vkGetPhysicalDeviceFeatures2`) must be loaded by calling the following command: + +```C++ +VkResult vpLoadInstance( + VpCapabilities capabilities, + VkInstance instance, + VpInstanceFunctionsLoadFlags flags); +``` + +Where: +* `capabilities` must be one of the capabilities handles returned from a call to `vpCreateCapabilities`. +* `instance` is the Vulkan instance to load the instance-level functions from. +* `flags` is a bitmask of `VpInstanceFunctionsLoadFlagBits` indicating additional entry point variants to try when loading. + +The `VpInstanceFunctionsLoadFlagBits` enumeration is defined as follows: + +```C++ +typedef enum VpInstanceFunctionsLoadFlagBits { + VP_INSTANCE_FUNCTIONS_LOAD_KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_BIT = (1 << 0), + VP_INSTANCE_FUNCTIONS_LOAD_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VpInstanceFunctionsLoadFlagBits; +``` + +If `VP_INSTANCE_FUNCTIONS_LOAD_KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_BIT` is specified, and the core `vkGetPhysicalDeviceFeatures2`/`vkGetPhysicalDeviceProperties2`/`vkGetPhysicalDeviceFormatProperties2`/`vkGetPhysicalDeviceQueueFamilyProperties2` entry points are not available, the library falls back to loading their `VK_KHR_get_physical_device_properties2` (`...KHR`) variants instead. This is useful when targeting a Vulkan 1.0 implementation that only supports the extension. + +`vpLoadInstance` must be called after `vpCreateInstance` (or after any other means of instance creation) and before querying device-level profile support or creating a device with `vpCreateDevice`. + #### Checking instance level support In order to query whether the Vulkan implementation supports the necessary instance level requirements (API version and instance extensions) of a particular profile, use the following command: diff --git a/library/test/CMakeLists.txt b/library/test/CMakeLists.txt index e64888ae..fa8e455c 100644 --- a/library/test/CMakeLists.txt +++ b/library/test/CMakeLists.txt @@ -235,3 +235,22 @@ add_unit_test_simple(test_mocked_api_create_device) if (NOT ANDROID) add_unit_test_simple(test_mocked_api_generated_library) endif() + +function(add_unit_test_no_prototypes NAME) + set(TEST_FILE ./${NAME}.cpp) + set(TEST_NAME VpLibrary_${NAME}) + + add_executable(${TEST_NAME} ${TEST_FILE}) + if(MSVC) + target_compile_options(${TEST_NAME} PRIVATE /bigobj) + endif() + target_compile_definitions(${TEST_NAME} PUBLIC "VK_NO_PROTOTYPES=1") + target_compile_definitions(${TEST_NAME} PUBLIC "VK_ENABLE_BETA_EXTENSIONS=1") + target_include_directories(${TEST_NAME} PUBLIC "${vulkan-headers_SOURCE_DIR}/include") + target_link_libraries(${TEST_NAME} PRIVATE GTest::gtest GTest::gtest_main Vulkan::Headers Vulkan::Profiles Vulkan::CompilerConfiguration Vulkan::CompilerConfigurationExtra) + add_dependencies(${TEST_NAME} VpGenerated VpLibrary_test_generated_library) + add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} --gtest_catch_exceptions=0) + set_target_properties(${TEST_NAME} PROPERTIES FOLDER "Profiles API library") +endfunction() + +add_unit_test_no_prototypes(test_api_no_prototypes_loading) diff --git a/library/test/mock_vulkan_api.hpp b/library/test/mock_vulkan_api.hpp index 8cb158ec..77e79d70 100644 --- a/library/test/mock_vulkan_api.hpp +++ b/library/test/mock_vulkan_api.hpp @@ -198,6 +198,18 @@ class MockVulkanAPI final , vkAllocator{} { sInstance = this; + + VpCapabilitiesCreateInfo createInfo{}; + VpVulkanFunctions vulkanFunctions{}; + vulkanFunctions.GetInstanceProcAddr = MockVulkanAPI::vkGetInstanceProcAddr; + vulkanFunctions.EnumerateInstanceExtensionProperties = MockVulkanAPI::vkEnumerateInstanceExtensionProperties; + vulkanFunctions.EnumerateDeviceExtensionProperties = MockVulkanAPI::vkEnumerateDeviceExtensionProperties; + vulkanFunctions.CreateInstance = MockVulkanAPI::vkCreateInstance; + vulkanFunctions.CreateDevice = MockVulkanAPI::vkCreateDevice; + createInfo.pVulkanFunctions = &vulkanFunctions; + createInfo.flags = VP_CAPABILITIES_CREATE_DYNAMIC_BIT; + vpInitialize(&createInfo); + vpLoadInstance(vkInstance, {}); } ~MockVulkanAPI() @@ -255,6 +267,7 @@ class MockVulkanAPI final void SetInstanceAPIVersion(uint32_t version) { + VpInstanceFunctionsLoadFlags loadInstanceFlags{}; m_instanceAPIVersion = version; if (version >= VK_API_VERSION_1_1) { AddInstanceProc(nullptr, "vkEnumerateInstanceVersion", &vkEnumerateInstanceVersion); @@ -275,7 +288,20 @@ class MockVulkanAPI final RemoveInstanceProc(vkInstance, "vkGetPhysicalDeviceProperties2"); RemoveInstanceProc(vkInstance, "vkGetPhysicalDeviceFormatProperties2"); RemoveInstanceProc(vkInstance, "vkGetPhysicalDeviceQueueFamilyProperties2"); - } + loadInstanceFlags = VP_INSTANCE_FUNCTIONS_LOAD_KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_BIT; + } + + VpCapabilitiesCreateInfo createInfo{}; + VpVulkanFunctions vulkanFunctions{}; + vulkanFunctions.GetInstanceProcAddr = MockVulkanAPI::vkGetInstanceProcAddr; + vulkanFunctions.EnumerateInstanceExtensionProperties = MockVulkanAPI::vkEnumerateInstanceExtensionProperties; + vulkanFunctions.EnumerateDeviceExtensionProperties = MockVulkanAPI::vkEnumerateDeviceExtensionProperties; + vulkanFunctions.CreateInstance = MockVulkanAPI::vkCreateInstance; + vulkanFunctions.CreateDevice = MockVulkanAPI::vkCreateDevice; + createInfo.pVulkanFunctions = &vulkanFunctions; + createInfo.flags = VP_CAPABILITIES_CREATE_DYNAMIC_BIT; + vpInitialize(&createInfo); + vpLoadInstance(vkInstance, loadInstanceFlags); } static VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceVersion( diff --git a/library/test/test_api_no_prototypes_loading.cpp b/library/test/test_api_no_prototypes_loading.cpp new file mode 100644 index 00000000..18b336f6 --- /dev/null +++ b/library/test/test_api_no_prototypes_loading.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021-2026 LunarG, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES 1 +#endif + +#ifndef VP_DISABLE_STATIC_LINKING +#define VP_DISABLE_STATIC_LINKING 1 +#endif + +#ifndef VULKAN_PROFILES_HEADER_ONLY +#include +#else +#include +#endif + +#include +#include + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + + int result = RUN_ALL_TESTS(); + + return result; +} + +TEST(no_prototypes, create_instance_with_dynamic_pointers) { + vk::detail::DispatchLoaderDynamic dl; + dl.init(); + + VpCapabilitiesCreateInfo cci{}; + cci.flags = VP_CAPABILITIES_CREATE_DYNAMIC_BIT; + VpVulkanFunctions vf{}; + vf.GetInstanceProcAddr = dl.vkGetInstanceProcAddr; + cci.pVulkanFunctions = &vf; + EXPECT_TRUE(vpInitialize(&cci) == VK_SUCCESS); + + VkApplicationInfo ai{}; + ai.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + ai.pApplicationName = "Testing scaffold"; + ai.applicationVersion = VK_MAKE_VERSION(1, 2, 0); + ai.pEngineName = "No Engine"; + ai.engineVersion = VK_MAKE_VERSION(1, 2, 0); + ai.apiVersion = VK_API_VERSION_1_2; + + VkInstanceCreateInfo ici{}; + ici.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + ici.pApplicationInfo = &ai; + +#if defined(__APPLE__) + const char* extensions[] = { VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME }; + ici.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + ici.enabledExtensionCount = 1; + ici.ppEnabledExtensionNames = extensions; +#endif + + VkInstance instance{}; + EXPECT_TRUE(dl.vkCreateInstance(&ici, nullptr, &instance) == VK_SUCCESS); + + EXPECT_TRUE(vpLoadInstance(instance, {}) == VK_SUCCESS); +} diff --git a/library/test/test_api_profile_object.cpp b/library/test/test_api_profile_object.cpp index 7c31ee57..4cb9f7e1 100644 --- a/library/test/test_api_profile_object.cpp +++ b/library/test/test_api_profile_object.cpp @@ -52,9 +52,10 @@ struct Capabilities { VpCapabilities handle = VK_NULL_HANDLE; Capabilities() { + vpCreateCapabilities(nullptr, &handle); + VpVulkanFunctions vulkanFunctions; vulkanFunctions.GetInstanceProcAddr = vkGetInstanceProcAddr; - vulkanFunctions.GetDeviceProcAddr = vkGetDeviceProcAddr; vulkanFunctions.EnumerateInstanceVersion = vkEnumerateInstanceVersion; vulkanFunctions.EnumerateInstanceExtensionProperties = vkEnumerateInstanceExtensionProperties; vulkanFunctions.EnumerateDeviceExtensionProperties = vkEnumerateDeviceExtensionProperties; @@ -66,11 +67,9 @@ struct Capabilities { vulkanFunctions.CreateDevice = vkCreateDevice; VpCapabilitiesCreateInfo createInfo; - createInfo.apiVersion = VK_API_VERSION_1_1; - createInfo.flags = VP_PROFILE_CREATE_STATIC_BIT; + createInfo.flags = VP_CAPABILITIES_CREATE_STATIC_BIT; createInfo.pVulkanFunctions = &vulkanFunctions; - - vpCreateCapabilities(&createInfo, nullptr, &handle); + vpInitialize(handle, &createInfo); } ~Capabilities() { diff --git a/library/test/test_mocked_api_create_device.cpp b/library/test/test_mocked_api_create_device.cpp index b5c52aa0..b76fc993 100644 --- a/library/test/test_mocked_api_create_device.cpp +++ b/library/test/test_mocked_api_create_device.cpp @@ -20,9 +20,10 @@ * - Daniel Rakos */ -#include "mock_vulkan_api.hpp" #include +#include "mock_vulkan_api.hpp" + TEST(mocked_api_create_device, default_extensions) { MockVulkanAPI mock; diff --git a/library/test/test_mocked_api_create_instance.cpp b/library/test/test_mocked_api_create_instance.cpp index 6392ae0b..9cfaf49f 100644 --- a/library/test/test_mocked_api_create_instance.cpp +++ b/library/test/test_mocked_api_create_instance.cpp @@ -20,9 +20,11 @@ * - Daniel Rakos */ -#include "mock_vulkan_api.hpp" +#include #include + #include "generated_vulkan_profiles.hpp" +#include "mock_vulkan_api.hpp" static void initInstanceExtensions(const VpProfileProperties& profile, std::vector& properties, std::vector& outExtensions) { diff --git a/library/test/test_mocked_api_generated_library.cpp b/library/test/test_mocked_api_generated_library.cpp index 44e0e2c0..286cbbf7 100644 --- a/library/test/test_mocked_api_generated_library.cpp +++ b/library/test/test_mocked_api_generated_library.cpp @@ -19,8 +19,8 @@ * - Christophe Riccio */ -#include "mock_vulkan_api.hpp" #include "test_vulkan_profiles.hpp" +#include "mock_vulkan_api.hpp" void initProfile(MockVulkanAPI& mock, const VpProfileProperties& profile, uint32_t apiVersion = VK_API_VERSION_1_3, int profileAreas = PROFILE_AREA_ALL_BITS) { diff --git a/library/test/test_mocked_api_get_instance_profile_support.cpp b/library/test/test_mocked_api_get_instance_profile_support.cpp index 85ff2c4c..c8d9ee94 100644 --- a/library/test/test_mocked_api_get_instance_profile_support.cpp +++ b/library/test/test_mocked_api_get_instance_profile_support.cpp @@ -19,16 +19,19 @@ * - Daniel Rakos */ -#include "mock_vulkan_api.hpp" -#include "mock_debug_message_callback.hpp" +#include #include +#include "mock_debug_message_callback.hpp" + #ifdef WITH_DEBUG_MESSAGES #include "generated_vulkan_profiles_debug.hpp" #else #include "generated_vulkan_profiles.hpp" #endif +#include "mock_vulkan_api.hpp" + TEST(mocked_api_get_instance_profile_support, vulkan10_supported) { MockVulkanAPI mock; diff --git a/library/test/test_mocked_api_get_physdev_profile_support.cpp b/library/test/test_mocked_api_get_physdev_profile_support.cpp index b2fca540..09097261 100644 --- a/library/test/test_mocked_api_get_physdev_profile_support.cpp +++ b/library/test/test_mocked_api_get_physdev_profile_support.cpp @@ -19,16 +19,19 @@ * - Daniel Rakos */ -#include "mock_vulkan_api.hpp" -#include "mock_debug_message_callback.hpp" +#include #include +#include "mock_debug_message_callback.hpp" + #ifdef WITH_DEBUG_MESSAGES #include "generated_vulkan_profiles_debug.hpp" #else #include "generated_vulkan_profiles.hpp" #endif +#include "mock_vulkan_api.hpp" + TEST(mocked_api_get_physdev_profile_support, vulkan10_supported) { MockVulkanAPI mock; diff --git a/scripts/gen_profiles_solution.py b/scripts/gen_profiles_solution.py index f614ff9c..4ef91e1b 100644 --- a/scripts/gen_profiles_solution.py +++ b/scripts/gen_profiles_solution.py @@ -213,21 +213,28 @@ def stripNonmatchingAPIs(tree, apiName, actuallyDelete = True): VK_DEFINE_HANDLE(VpCapabilities) typedef enum VpCapabilitiesCreateFlagBits { - VP_PROFILE_CREATE_STATIC_BIT = (1 << 0), - //VP_PROFILE_CREATE_DYNAMIC_BIT = (1 << 1), - VP_PROFILE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +#ifndef VK_NO_PROTOTYPES + VP_CAPABILITIES_CREATE_STATIC_BIT = (1 << 0), +#endif//VK_NO_PROTOTYPES + VP_CAPABILITIES_CREATE_DYNAMIC_BIT = (1 << 1), + VP_CAPABILITIES_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF } VpCapabilitiesCreateFlagBits; typedef VkFlags VpCapabilitiesCreateFlags; +typedef enum VpInstanceFunctionsLoadFlagBits { + VP_INSTANCE_FUNCTIONS_LOAD_KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_BIT = (1 << 0), + VP_INSTANCE_FUNCTIONS_LOAD_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF +} VpInstanceFunctionsLoadFlagBits; + +typedef VkFlags VpInstanceFunctionsLoadFlags; + // Pointers to some Vulkan functions - a subset used by the library. // Used in VpCapabilitiesCreateInfo::pVulkanFunctions. typedef struct VpVulkanFunctions { /// Required when using VP_DYNAMIC_VULKAN_FUNCTIONS. PFN_vkGetInstanceProcAddr GetInstanceProcAddr; - /// Required when using VP_DYNAMIC_VULKAN_FUNCTIONS. - PFN_vkGetDeviceProcAddr GetDeviceProcAddr; PFN_vkEnumerateInstanceVersion EnumerateInstanceVersion; PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties; PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties; @@ -244,12 +251,10 @@ def stripNonmatchingAPIs(tree, apiName, actuallyDelete = True): { /// Flags for created allocator. Use #VpInstanceCreateFlagBits enum. VpCapabilitiesCreateFlags flags; - uint32_t apiVersion; const VpVulkanFunctions* pVulkanFunctions; } VpCapabilitiesCreateInfo; VPAPI_ATTR VkResult vpCreateCapabilities( - const VpCapabilitiesCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VpCapabilities* pCapabilities); @@ -258,6 +263,21 @@ def stripNonmatchingAPIs(tree, apiName, actuallyDelete = True): VpCapabilities capabilities, const VkAllocationCallbacks* pAllocator); +/// Initializes capabilities with global functions +VPAPI_ATTR VkResult vpInitialize( +#ifdef VP_USE_OBJECT + VpCapabilities capabilities, +#endif//VP_USE_OBJECT + const VpCapabilitiesCreateInfo* pCreateInfo); + +/// Initializes capabilities with instance functions +VPAPI_ATTR VkResult vpLoadInstance( +#ifdef VP_USE_OBJECT + VpCapabilities capabilities, +#endif//VP_USE_OBJECT + VkInstance instance, + VpInstanceFunctionsLoadFlags flags); + // Query the list of available profiles in the library VPAPI_ATTR VkResult vpGetProfiles( #ifdef VP_USE_OBJECT @@ -1153,21 +1173,25 @@ def stripNonmatchingAPIs(tree, apiName, actuallyDelete = True): PUBLIC_IMPL_BODY = ''' struct VpCapabilities_T : public VpVulkanFunctions { - bool singleton = false; - uint32_t apiVersion = VK_API_VERSION_1_0; + bool initialized = false; static VpCapabilities_T& Get() { static VpCapabilities_T instance; - VpCapabilitiesCreateInfo createInfo{}; - createInfo.flags = VP_PROFILE_CREATE_STATIC_BIT; - instance.init(&createInfo); - instance.singleton = true; + +#ifndef VK_NO_PROTOTYPES + if (!instance.initialized) { + VpCapabilitiesCreateInfo createInfo{}; + createInfo.flags = VP_CAPABILITIES_CREATE_STATIC_BIT; + instance.init(&createInfo); + instance.initialized = true; + } +#endif//VK_NO_PROTOTYPES + return instance; } VpCapabilities_T() { this->GetInstanceProcAddr = nullptr; - this->GetDeviceProcAddr = nullptr; this->EnumerateInstanceVersion = nullptr; this->EnumerateInstanceExtensionProperties = nullptr; this->EnumerateDeviceExtensionProperties = nullptr; @@ -1182,155 +1206,166 @@ def stripNonmatchingAPIs(tree, apiName, actuallyDelete = True): VkResult init(const VpCapabilitiesCreateInfo* pCreateInfo) { assert(pCreateInfo != nullptr); - return ImportVulkanFunctions(pCreateInfo); - } + ImportVulkanFunctions_Custom(pCreateInfo->pVulkanFunctions); - VkResult ImportVulkanFunctions(const VpCapabilitiesCreateInfo* pCreateInfo) { - if (pCreateInfo->flags & VP_PROFILE_CREATE_STATIC_BIT) { - ImportVulkanFunctions_Static(); + if (pCreateInfo->flags & VP_CAPABILITIES_CREATE_DYNAMIC_BIT) { + if (!pCreateInfo->pVulkanFunctions) { + return VK_ERROR_INITIALIZATION_FAILED; + } + if (!pCreateInfo->pVulkanFunctions->GetInstanceProcAddr) { + return VK_ERROR_INITIALIZATION_FAILED; + } + ImportGlobalVulkanFunctions_Dynamic(pCreateInfo->pVulkanFunctions->GetInstanceProcAddr); + return ValidateGlobalVulkanFunctions(); } - if (pCreateInfo->pVulkanFunctions != nullptr) { - ImportVulkanFunctions_Custom((VpVulkanFunctions*)pCreateInfo->pVulkanFunctions); - } -/* - if (pCreateInfo->flags & VP_PROFILE_CREATE_DYNAMIC_BIT) { - ImportVulkanFunctions_Dynamic(); +#ifndef VK_NO_PROTOTYPES + if (pCreateInfo->flags & VP_CAPABILITIES_CREATE_STATIC_BIT) { + ImportVulkanFunctions_Static(); } -*/ - return ValidateVulkanFunctions(); +#endif//VK_NO_PROTOTYPES + + VkResult result = ValidateGlobalVulkanFunctions(); + return result != VK_SUCCESS ? result : ValidateInstanceVulkanFunctions({}); } +#ifndef VK_NO_PROTOTYPES void ImportVulkanFunctions_Static() { - // Vulkan 1.1 - this->GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)vkGetInstanceProcAddr; - this->GetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetDeviceProcAddr; +#define VP_SET_STATIC(memberName, staticFuncName) \ + if (this->memberName == nullptr) \ + this->memberName = (PFN_vk##memberName)staticFuncName + + VP_SET_STATIC(GetInstanceProcAddr, vkGetInstanceProcAddr); + + VP_SET_STATIC(EnumerateInstanceVersion, vkEnumerateInstanceVersion); + VP_SET_STATIC(EnumerateInstanceExtensionProperties, vkEnumerateInstanceExtensionProperties); + VP_SET_STATIC(EnumerateDeviceExtensionProperties, vkEnumerateDeviceExtensionProperties); - this->EnumerateInstanceVersion = (PFN_vkEnumerateInstanceVersion)vkEnumerateInstanceVersion; - this->EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)vkEnumerateInstanceExtensionProperties; - this->EnumerateDeviceExtensionProperties = (PFN_vkEnumerateDeviceExtensionProperties)vkEnumerateDeviceExtensionProperties; + VP_SET_STATIC(GetPhysicalDeviceFeatures2, vkGetPhysicalDeviceFeatures2); + VP_SET_STATIC(GetPhysicalDeviceProperties2, vkGetPhysicalDeviceProperties2); + VP_SET_STATIC(GetPhysicalDeviceFormatProperties2, vkGetPhysicalDeviceFormatProperties2); + VP_SET_STATIC(GetPhysicalDeviceQueueFamilyProperties2, vkGetPhysicalDeviceQueueFamilyProperties2); - this->GetPhysicalDeviceFeatures2 = (PFN_vkGetPhysicalDeviceFeatures2)vkGetPhysicalDeviceFeatures2; - this->GetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2)vkGetPhysicalDeviceProperties2; - this->GetPhysicalDeviceFormatProperties2 = (PFN_vkGetPhysicalDeviceFormatProperties2)vkGetPhysicalDeviceFormatProperties2; - this->GetPhysicalDeviceQueueFamilyProperties2 = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2)vkGetPhysicalDeviceQueueFamilyProperties2; + VP_SET_STATIC(CreateInstance, vkCreateInstance); + VP_SET_STATIC(CreateDevice, vkCreateDevice); - this->CreateInstance = (PFN_vkCreateInstance)vkCreateInstance; - this->CreateDevice = (PFN_vkCreateDevice)vkCreateDevice; +#undef VP_SET_STATIC } +#endif//VK_NO_PROTOTYPES - void ImportVulkanFunctions_Custom(VpVulkanFunctions* pFunctions) { - #define VP_COPY_IF_NOT_NULL(funcName) \ - if(pFunctions->funcName != nullptr) this->funcName = pFunctions->funcName; + void ImportGlobalVulkanFunctions_Dynamic(PFN_vkGetInstanceProcAddr getInstanceProcAddr) { + this->GetInstanceProcAddr = getInstanceProcAddr; - VP_COPY_IF_NOT_NULL(GetInstanceProcAddr); - VP_COPY_IF_NOT_NULL(GetDeviceProcAddr); +#define VP_FETCH_FUNC(memberName, functionNameString) \ + if(this->memberName == nullptr) \ + this->memberName = (PFN_vk##memberName)this->GetInstanceProcAddr(nullptr, functionNameString) - VP_COPY_IF_NOT_NULL(EnumerateInstanceVersion); - VP_COPY_IF_NOT_NULL(EnumerateInstanceExtensionProperties); - VP_COPY_IF_NOT_NULL(EnumerateDeviceExtensionProperties); + VP_FETCH_FUNC(EnumerateInstanceVersion, "vkEnumerateInstanceVersion"); + VP_FETCH_FUNC(EnumerateInstanceExtensionProperties, "vkEnumerateInstanceExtensionProperties"); - VP_COPY_IF_NOT_NULL(GetPhysicalDeviceFeatures2); - VP_COPY_IF_NOT_NULL(GetPhysicalDeviceProperties2); - VP_COPY_IF_NOT_NULL(GetPhysicalDeviceFormatProperties2); - VP_COPY_IF_NOT_NULL(GetPhysicalDeviceQueueFamilyProperties2); + VP_FETCH_FUNC(CreateInstance, "vkCreateInstance"); - VP_COPY_IF_NOT_NULL(CreateInstance); - VP_COPY_IF_NOT_NULL(CreateDevice); - #undef VP_COPY_IF_NOT_NULL +#undef VP_FETCH_FUNC } -/* - VkResult ImportVulkanFunctions_Dynamic() { - // To use VP_PROFILE_CREATE_DYNAMIC_BIT you have to pass VpVulkanFunctions::vkGetInstanceProcAddr and vkGetDeviceProcAddr as VpCapabilitiesCreateInfo::pVulkanFunctions. Other members can be null. - if (this->GetInstanceProcAddr == nullptr || this->GetDeviceProcAddr == nullptr) { + + VkResult ValidateGlobalVulkanFunctions() { + // vkEnumerateInstanceVersion is omitted from validation on purpose. + // It is not available in Vulkan 1.0, and nullptr is a valid state indicating Vulkan 1.0. + + if (this->EnumerateInstanceExtensionProperties == nullptr || + this->CreateInstance == nullptr || + this->GetInstanceProcAddr == nullptr) { return VK_ERROR_INITIALIZATION_FAILED; } - #define VP_FETCH_INSTANCE_FUNC(memberName, functionNameString) \ - if(this->memberName == nullptr) \ - this->memberName = (PFN_vk##memberName)this->GetInstanceProcAddr(m_hInstance, functionNameString); - #define VP_FETCH_DEVICE_FUNC(memberName, functionNameString) \ - if(this->memberName == nullptr) \ - this->memberName = (PFN_vk##memberName)this->GetDeviceProcAddr(m_hDevice, functionNameString); - - VP_FETCH_INSTANCE_FUNC(GetInstanceProcAddr, "vkGetInstanceProcAddr"); - VP_FETCH_DEVICE_FUNC(GetDeviceProcAddr, "vkGetDeviceProcAddr"); - - VP_FETCH_INSTANCE_FUNC(EnumerateInstanceVersion, "vkEnumerateInstanceVersion"); - VP_FETCH_INSTANCE_FUNC(EnumerateInstanceExtensionProperties, "vkEnumerateInstanceExtensionProperties"); - VP_FETCH_DEVICE_FUNC(EnumerateDeviceExtensionProperties, "vkEnumerateDeviceExtensionProperties"); - - VP_FETCH_DEVICE_FUNC(GetPhysicalDeviceFeatures2, "vkGetPhysicalDeviceFeatures2"); - VP_FETCH_DEVICE_FUNC(GetPhysicalDeviceProperties2, "vkGetPhysicalDeviceProperties2"); - VP_FETCH_DEVICE_FUNC(GetPhysicalDeviceFormatProperties2, "vkGetPhysicalDeviceFormatProperties2"); - VP_FETCH_DEVICE_FUNC(GetPhysicalDeviceQueueFamilyProperties2, "vkGetPhysicalDeviceQueueFamilyProperties2"); - - VP_FETCH_INSTANCE_FUNC(CreateInstance, "vkCreateInstance"); - VP_FETCH_DEVICE_FUNC(CreateDevice, "vkCreateDevice"); - #undef VP_FETCH_DEVICE_FUNC - #undef VP_FETCH_INSTANCE_FUNC + return VK_SUCCESS; } -*/ - VkResult ValidateVulkanFunctions() { - if (this->GetInstanceProcAddr == nullptr) { - return VK_ERROR_INITIALIZATION_FAILED; + + void ImportInstanceVulkanFunctions_Dynamic(VkInstance instance, VpInstanceFunctionsLoadFlags flags) { +#define VP_FETCH_FUNC(memberName, functionNameString) \ + if(this->memberName == nullptr) \ + this->memberName = (PFN_vk##memberName)this->GetInstanceProcAddr(instance, functionNameString); + + VP_FETCH_FUNC(EnumerateDeviceExtensionProperties, "vkEnumerateDeviceExtensionProperties"); + VP_FETCH_FUNC(GetPhysicalDeviceFeatures2, "vkGetPhysicalDeviceFeatures2"); + if (!this->GetPhysicalDeviceFeatures2 && (flags & VP_INSTANCE_FUNCTIONS_LOAD_KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_BIT)) { + VP_FETCH_FUNC(GetPhysicalDeviceFeatures2, "vkGetPhysicalDeviceFeatures2KHR"); } - if (this->GetDeviceProcAddr == nullptr) { - return VK_ERROR_INITIALIZATION_FAILED; + VP_FETCH_FUNC(GetPhysicalDeviceProperties2, "vkGetPhysicalDeviceProperties2"); + if (!this->GetPhysicalDeviceProperties2 && (flags & VP_INSTANCE_FUNCTIONS_LOAD_KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_BIT)) { + VP_FETCH_FUNC(GetPhysicalDeviceProperties2, "vkGetPhysicalDeviceProperties2KHR"); } - if (this->EnumerateInstanceVersion == nullptr && apiVersion >= VK_API_VERSION_1_1) { - return VK_ERROR_INITIALIZATION_FAILED; + VP_FETCH_FUNC(GetPhysicalDeviceFormatProperties2, "vkGetPhysicalDeviceFormatProperties2"); + if (!this->GetPhysicalDeviceFormatProperties2 && (flags & VP_INSTANCE_FUNCTIONS_LOAD_KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_BIT)) { + VP_FETCH_FUNC(GetPhysicalDeviceFormatProperties2, "vkGetPhysicalDeviceFormatProperties2KHR"); } - if (this->EnumerateInstanceExtensionProperties == nullptr) { - return VK_ERROR_INITIALIZATION_FAILED; + VP_FETCH_FUNC(GetPhysicalDeviceQueueFamilyProperties2, "vkGetPhysicalDeviceQueueFamilyProperties2"); + if (!this->GetPhysicalDeviceQueueFamilyProperties2 && (flags & VP_INSTANCE_FUNCTIONS_LOAD_KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_BIT)) { + VP_FETCH_FUNC(GetPhysicalDeviceQueueFamilyProperties2, "vkGetPhysicalDeviceQueueFamilyProperties2KHR"); } - if (this->EnumerateDeviceExtensionProperties == nullptr) { + VP_FETCH_FUNC(CreateDevice, "vkCreateDevice"); + +#undef VP_FETCH_FUNC + } + + VkResult ValidateInstanceVulkanFunctions(VpInstanceFunctionsLoadFlags flags) { + if (this->EnumerateDeviceExtensionProperties == nullptr || + this->CreateDevice == nullptr) { return VK_ERROR_INITIALIZATION_FAILED; } - if (this->GetPhysicalDeviceFeatures2 == nullptr) { - return apiVersion >= VK_API_VERSION_1_1 ? VK_ERROR_INITIALIZATION_FAILED : VK_ERROR_EXTENSION_NOT_PRESENT; - } + bool requiresProperties2 = (flags & VP_INSTANCE_FUNCTIONS_LOAD_KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_BIT); - if (this->GetPhysicalDeviceProperties2 == nullptr) { - return apiVersion >= VK_API_VERSION_1_1 ? VK_ERROR_INITIALIZATION_FAILED : VK_ERROR_EXTENSION_NOT_PRESENT; + if (this->GetPhysicalDeviceFeatures2 == nullptr || + this->GetPhysicalDeviceProperties2 == nullptr || + this->GetPhysicalDeviceFormatProperties2 == nullptr || + this->GetPhysicalDeviceQueueFamilyProperties2 == nullptr) { + return requiresProperties2 ? VK_ERROR_INITIALIZATION_FAILED : VK_ERROR_EXTENSION_NOT_PRESENT; } - if (this->GetPhysicalDeviceFormatProperties2 == nullptr) { - return apiVersion >= VK_API_VERSION_1_1 ? VK_ERROR_INITIALIZATION_FAILED : VK_ERROR_EXTENSION_NOT_PRESENT; - } + return VK_SUCCESS; + } - if (this->GetPhysicalDeviceQueueFamilyProperties2 == nullptr) { - return apiVersion >= VK_API_VERSION_1_1 ? VK_ERROR_INITIALIZATION_FAILED : VK_ERROR_EXTENSION_NOT_PRESENT; + void ImportVulkanFunctions_Custom(const VpVulkanFunctions* functions) { + if (!functions) { + return; } - if (this->CreateInstance == nullptr) { - return VK_ERROR_INITIALIZATION_FAILED; - } +#define VP_COPY_IF_NOT_NULL(funcName) \ + if(functions->funcName != nullptr) \ + this->funcName = functions->funcName; - if (this->CreateDevice == nullptr) { - return VK_ERROR_INITIALIZATION_FAILED; - } + VP_COPY_IF_NOT_NULL(GetInstanceProcAddr); - return VK_SUCCESS; + VP_COPY_IF_NOT_NULL(EnumerateInstanceVersion); + VP_COPY_IF_NOT_NULL(EnumerateInstanceExtensionProperties); + VP_COPY_IF_NOT_NULL(EnumerateDeviceExtensionProperties); + + VP_COPY_IF_NOT_NULL(GetPhysicalDeviceFeatures2); + VP_COPY_IF_NOT_NULL(GetPhysicalDeviceProperties2); + VP_COPY_IF_NOT_NULL(GetPhysicalDeviceFormatProperties2); + VP_COPY_IF_NOT_NULL(GetPhysicalDeviceQueueFamilyProperties2); + + VP_COPY_IF_NOT_NULL(CreateInstance); + VP_COPY_IF_NOT_NULL(CreateDevice); +#undef VP_COPY_IF_NOT_NULL } }; VPAPI_ATTR VkResult vpCreateCapabilities( - const VpCapabilitiesCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VpCapabilities* pCapabilities) { (void)pAllocator; - - VpCapabilities_T* capabilities = new VpCapabilities_T(); - VkResult result = capabilities->init(pCreateInfo); + VpCapabilities_T* capabilities = new (std::nothrow) VpCapabilities_T(); *pCapabilities = capabilities; - - return result; + if (!capabilities) { + return VK_ERROR_INITIALIZATION_FAILED; + } + return VK_SUCCESS; } /// Destroys allocator object. @@ -1342,6 +1377,41 @@ def stripNonmatchingAPIs(tree, apiName, actuallyDelete = True): delete capabilities; } +/// Initializes capabilities with global functions +VPAPI_ATTR VkResult vpInitialize( +#ifdef VP_USE_OBJECT + VpCapabilities capabilities, +#endif//VP_USE_OBJECT + const VpCapabilitiesCreateInfo* pCreateInfo) { +#ifdef VP_USE_OBJECT + VpCapabilities_T& vp = capabilities == nullptr ? VpCapabilities_T::Get() : *capabilities; +#else + VpCapabilities_T& vp = VpCapabilities_T::Get(); +#endif//VP_USE_OBJECT + + // Reset before initializing + vp = VpCapabilities_T {}; + vp.initialized = true; + return vp.init(pCreateInfo); +} + +/// Initializes capabilities with instance functions +VPAPI_ATTR VkResult vpLoadInstance( +#ifdef VP_USE_OBJECT + VpCapabilities capabilities, +#endif//VP_USE_OBJECT + VkInstance instance, + VpInstanceFunctionsLoadFlags flags) { +#ifdef VP_USE_OBJECT + VpCapabilities_T& vp = capabilities == nullptr ? VpCapabilities_T::Get() : *capabilities; +#else + VpCapabilities_T& vp = VpCapabilities_T::Get(); +#endif//VP_USE_OBJECT + + vp.ImportInstanceVulkanFunctions_Dynamic(instance, flags); + return vp.ValidateInstanceVulkanFunctions(flags); +} + VPAPI_ATTR VkResult vpGetProfiles( #ifdef VP_USE_OBJECT VpCapabilities capabilities, @@ -1512,8 +1582,7 @@ def stripNonmatchingAPIs(tree, apiName, actuallyDelete = True): VkResult result = VK_SUCCESS; uint32_t api_version = VK_API_VERSION_1_0; - PFN_vkEnumerateInstanceVersion pfnEnumerateInstanceVersion = vp.singleton ? - (PFN_vkEnumerateInstanceVersion)vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceVersion") : vp.EnumerateInstanceVersion; + PFN_vkEnumerateInstanceVersion pfnEnumerateInstanceVersion = vp.EnumerateInstanceVersion; if (pfnEnumerateInstanceVersion != nullptr) { result = pfnEnumerateInstanceVersion(&api_version); if (result != VK_SUCCESS) { @@ -1793,36 +1862,10 @@ def stripNonmatchingAPIs(tree, apiName, actuallyDelete = True): bool supported; } userData{physicalDevice, supported_blocks, unsupported_blocks}; - if (!vp.singleton) { - userData.gpdp2.pfnGetPhysicalDeviceFeatures2 = vp.GetPhysicalDeviceFeatures2; - userData.gpdp2.pfnGetPhysicalDeviceProperties2 = vp.GetPhysicalDeviceProperties2; - userData.gpdp2.pfnGetPhysicalDeviceFormatProperties2 = vp.GetPhysicalDeviceFormatProperties2; - userData.gpdp2.pfnGetPhysicalDeviceQueueFamilyProperties2 = vp.GetPhysicalDeviceQueueFamilyProperties2; - } - - // Attempt to load core versions of the GPDP2 entry points - if (userData.gpdp2.pfnGetPhysicalDeviceFeatures2 == nullptr) { - userData.gpdp2.pfnGetPhysicalDeviceFeatures2 = - (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2"); - userData.gpdp2.pfnGetPhysicalDeviceProperties2 = - (PFN_vkGetPhysicalDeviceProperties2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2"); - userData.gpdp2.pfnGetPhysicalDeviceFormatProperties2 = - (PFN_vkGetPhysicalDeviceFormatProperties2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2"); - userData.gpdp2.pfnGetPhysicalDeviceQueueFamilyProperties2 = - (PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties2"); - } - - // If not successful, try to load KHR variant - if (userData.gpdp2.pfnGetPhysicalDeviceFeatures2 == nullptr) { - userData.gpdp2.pfnGetPhysicalDeviceFeatures2 = - (PFN_vkGetPhysicalDeviceFeatures2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFeatures2KHR"); - userData.gpdp2.pfnGetPhysicalDeviceProperties2 = - (PFN_vkGetPhysicalDeviceProperties2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceProperties2KHR"); - userData.gpdp2.pfnGetPhysicalDeviceFormatProperties2 = - (PFN_vkGetPhysicalDeviceFormatProperties2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceFormatProperties2KHR"); - userData.gpdp2.pfnGetPhysicalDeviceQueueFamilyProperties2 = - (PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceQueueFamilyProperties2KHR"); - } + userData.gpdp2.pfnGetPhysicalDeviceFeatures2 = vp.GetPhysicalDeviceFeatures2; + userData.gpdp2.pfnGetPhysicalDeviceProperties2 = vp.GetPhysicalDeviceProperties2; + userData.gpdp2.pfnGetPhysicalDeviceFormatProperties2 = vp.GetPhysicalDeviceFormatProperties2; + userData.gpdp2.pfnGetPhysicalDeviceQueueFamilyProperties2 = vp.GetPhysicalDeviceQueueFamilyProperties2; if (userData.gpdp2.pfnGetPhysicalDeviceFeatures2 == nullptr || userData.gpdp2.pfnGetPhysicalDeviceProperties2 == nullptr || @@ -1832,7 +1875,7 @@ def stripNonmatchingAPIs(tree, apiName, actuallyDelete = True): } #ifdef VK_KHR_video_queue - PFN_vkGetInstanceProcAddr gipa = vp.singleton ? vkGetInstanceProcAddr : vp.GetInstanceProcAddr; + PFN_vkGetInstanceProcAddr gipa = vp.GetInstanceProcAddr; userData.video.pfnGetPhysicalDeviceVideoCapabilitiesKHR = (PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR)gipa(instance, "vkGetPhysicalDeviceVideoCapabilitiesKHR"); userData.video.pfnGetPhysicalDeviceVideoFormatPropertiesKHR =