diff options
-rw-r--r-- | vulkan/libvulkan/driver.cpp | 57 | ||||
-rw-r--r-- | vulkan/libvulkan/driver_gen.cpp | 48 | ||||
-rw-r--r-- | vulkan/libvulkan/driver_gen.h | 8 | ||||
-rw-r--r-- | vulkan/scripts/driver_generator.py | 56 | ||||
-rw-r--r-- | vulkan/scripts/generator_common.py | 17 |
5 files changed, 173 insertions, 13 deletions
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp index 3e31a66d78..c48d1eebf7 100644 --- a/vulkan/libvulkan/driver.cpp +++ b/vulkan/libvulkan/driver.cpp @@ -141,6 +141,7 @@ class CreateInfoWrapper { }; VkApplicationInfo application_info_; + uint32_t sanitized_api_version_; ExtensionFilter extension_filter_; @@ -329,6 +330,7 @@ CreateInfoWrapper::CreateInfoWrapper(const VkInstanceCreateInfo& create_info, loader_api_version_(VK_API_VERSION_1_1), physical_dev_(VK_NULL_HANDLE), instance_info_(create_info), + sanitized_api_version_(loader_api_version_), extension_filter_() {} CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev, @@ -385,10 +387,6 @@ VkResult CreateInfoWrapper::SanitizeApiVersion() { hal_extensions_.set(i); } - // If pApplicationInfo is NULL, apiVersion is assumed to be 1.0 - if (!instance_info_.pApplicationInfo) - return VK_SUCCESS; - uint32_t icd_api_version = VK_API_VERSION_1_0; PFN_vkEnumerateInstanceVersion pfn_enumerate_instance_version = reinterpret_cast<PFN_vkEnumerateInstanceVersion>( @@ -409,8 +407,13 @@ VkResult CreateInfoWrapper::SanitizeApiVersion() { return VK_SUCCESS; if (icd_api_version < loader_api_version_) { + sanitized_api_version_ = icd_api_version; + + if (!instance_info_.pApplicationInfo) + return VK_SUCCESS; + application_info_ = *instance_info_.pApplicationInfo; - application_info_.apiVersion = icd_api_version; + application_info_.apiVersion = sanitized_api_version_; instance_info_.pApplicationInfo = &application_info_; } } else { @@ -498,15 +501,33 @@ VkResult CreateInfoWrapper::SanitizeExtensions() { : dev_info_.ppEnabledExtensionNames; auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount : dev_info_.enabledExtensionCount; - if (!ext_count) - return VK_SUCCESS; VkResult result = InitExtensionFilter(); if (result != VK_SUCCESS) return result; - for (uint32_t i = 0; i < ext_count; i++) - FilterExtension(ext_names[i]); + if (is_instance_ && sanitized_api_version_ < loader_api_version_) { + for (uint32_t i = 0; i < ext_count; i++) { + // Upon api downgrade, skip the promoted instance extensions in the + // first pass to avoid duplicate extensions. + const std::optional<uint32_t> version = + GetInstanceExtensionPromotedVersion(ext_names[i]); + if (version && *version > sanitized_api_version_ && + *version <= loader_api_version_) + continue; + + FilterExtension(ext_names[i]); + } + + // Enable the required extensions to support core functionalities. + const auto promoted_extensions = GetPromotedInstanceExtensions( + sanitized_api_version_, loader_api_version_); + for (const auto& promoted_extension : promoted_extensions) + FilterExtension(promoted_extension); + } else { + for (uint32_t i = 0; i < ext_count; i++) + FilterExtension(ext_names[i]); + } // Enable device extensions that contain physical-device commands, so that // vkGetInstanceProcAddr will return those physical-device commands. @@ -571,10 +592,20 @@ VkResult CreateInfoWrapper::InitExtensionFilter() { filter.ext_count = count; // allocate name array - uint32_t enabled_ext_count = (is_instance_) - ? instance_info_.enabledExtensionCount - : dev_info_.enabledExtensionCount; - count = std::min(filter.ext_count, enabled_ext_count); + if (is_instance_) { + uint32_t enabled_ext_count = instance_info_.enabledExtensionCount; + + // It requires enabling additional promoted extensions to downgrade api, + // so we reserve enough space here. + if (sanitized_api_version_ < loader_api_version_) { + enabled_ext_count += CountPromotedInstanceExtensions( + sanitized_api_version_, loader_api_version_); + } + + count = std::min(filter.ext_count, enabled_ext_count); + } else { + count = std::min(filter.ext_count, dev_info_.enabledExtensionCount); + } filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation( allocator_.pUserData, sizeof(const char*) * count, alignof(const char*), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)); diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp index 52205e9e79..39fd15a6cc 100644 --- a/vulkan/libvulkan/driver_gen.cpp +++ b/vulkan/libvulkan/driver_gen.cpp @@ -577,5 +577,53 @@ bool InitDriverTable(VkDevice dev, return success; } +const std::pair<const char*, uint32_t> g_promoted_instance_extensions[] = { + // clang-format off + std::make_pair("VK_KHR_device_group_creation", VK_API_VERSION_1_1), + std::make_pair("VK_KHR_external_fence_capabilities", VK_API_VERSION_1_1), + std::make_pair("VK_KHR_external_memory_capabilities", VK_API_VERSION_1_1), + std::make_pair("VK_KHR_external_semaphore_capabilities", VK_API_VERSION_1_1), + std::make_pair("VK_KHR_get_physical_device_properties2", VK_API_VERSION_1_1), + // clang-format on +}; + +std::optional<uint32_t> GetInstanceExtensionPromotedVersion(const char* name) { + auto begin = std::cbegin(g_promoted_instance_extensions); + auto end = std::cend(g_promoted_instance_extensions); + auto iter = + std::lower_bound(begin, end, name, + [](const std::pair<const char*, uint32_t>& e, + const char* n) { return strcmp(e.first, n) < 0; }); + return (iter < end && strcmp(iter->first, name) == 0) + ? std::optional<uint32_t>(iter->second) + : std::nullopt; +} + +uint32_t CountPromotedInstanceExtensions(uint32_t begin_version, + uint32_t end_version) { + auto begin = std::cbegin(g_promoted_instance_extensions); + auto end = std::cend(g_promoted_instance_extensions); + uint32_t count = 0; + + for (auto iter = begin; iter != end; iter++) + if (iter->second > begin_version && iter->second <= end_version) + count++; + + return count; +} + +std::vector<const char*> GetPromotedInstanceExtensions(uint32_t begin_version, + uint32_t end_version) { + auto begin = std::cbegin(g_promoted_instance_extensions); + auto end = std::cend(g_promoted_instance_extensions); + std::vector<const char*> extensions; + + for (auto iter = begin; iter != end; iter++) + if (iter->second > begin_version && iter->second <= end_version) + extensions.emplace_back(iter->first); + + return extensions; +} + } // namespace driver } // namespace vulkan diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h index 43c4d1469e..4669c25dd8 100644 --- a/vulkan/libvulkan/driver_gen.h +++ b/vulkan/libvulkan/driver_gen.h @@ -23,6 +23,8 @@ #include <vulkan/vulkan.h> #include <bitset> +#include <optional> +#include <vector> namespace vulkan { namespace driver { @@ -109,6 +111,12 @@ bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc, const std::bitset<ProcHook::EXTENSION_COUNT>& extensions); +std::optional<uint32_t> GetInstanceExtensionPromotedVersion(const char* name); +uint32_t CountPromotedInstanceExtensions(uint32_t begin_version, + uint32_t end_version); +std::vector<const char*> GetPromotedInstanceExtensions(uint32_t begin_version, + uint32_t end_version); + } // namespace driver } // namespace vulkan diff --git a/vulkan/scripts/driver_generator.py b/vulkan/scripts/driver_generator.py index a64a7026db..5e78c62df8 100644 --- a/vulkan/scripts/driver_generator.py +++ b/vulkan/scripts/driver_generator.py @@ -162,6 +162,8 @@ def gen_h(): #include <vulkan/vulkan.h> #include <bitset> +#include <optional> +#include <vector> namespace vulkan { namespace driver { @@ -229,6 +231,12 @@ bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc, const std::bitset<ProcHook::EXTENSION_COUNT>& extensions); +std::optional<uint32_t> GetInstanceExtensionPromotedVersion(const char* name); +uint32_t CountPromotedInstanceExtensions(uint32_t begin_version, + uint32_t end_version); +std::vector<const char*> GetPromotedInstanceExtensions(uint32_t begin_version, + uint32_t end_version); + } // namespace driver } // namespace vulkan @@ -539,6 +547,54 @@ bool InitDriverTable(VkDevice dev, return success; } +const std::pair<const char*, uint32_t> g_promoted_instance_extensions[] = { + // clang-format off\n""") + + for key, value in sorted(gencom.promoted_inst_ext_dict.items()): + f.write(gencom.indent(1) + 'std::make_pair("' + key + '", ' + value + '),\n') + + f.write("""\ + // clang-format on +}; + +std::optional<uint32_t> GetInstanceExtensionPromotedVersion(const char* name) { + auto begin = std::cbegin(g_promoted_instance_extensions); + auto end = std::cend(g_promoted_instance_extensions); + auto iter = + std::lower_bound(begin, end, name, + [](const std::pair<const char*, uint32_t>& e, + const char* n) { return strcmp(e.first, n) < 0; }); + return (iter < end && strcmp(iter->first, name) == 0) + ? std::optional<uint32_t>(iter->second) + : std::nullopt; +} + +uint32_t CountPromotedInstanceExtensions(uint32_t begin_version, + uint32_t end_version) { + auto begin = std::cbegin(g_promoted_instance_extensions); + auto end = std::cend(g_promoted_instance_extensions); + uint32_t count = 0; + + for (auto iter = begin; iter != end; iter++) + if (iter->second > begin_version && iter->second <= end_version) + count++; + + return count; +} + +std::vector<const char*> GetPromotedInstanceExtensions(uint32_t begin_version, + uint32_t end_version) { + auto begin = std::cbegin(g_promoted_instance_extensions); + auto end = std::cend(g_promoted_instance_extensions); + std::vector<const char*> extensions; + + for (auto iter = begin; iter != end; iter++) + if (iter->second > begin_version && iter->second <= end_version) + extensions.emplace_back(iter->first); + + return extensions; +} + } // namespace driver } // namespace vulkan\n""") diff --git a/vulkan/scripts/generator_common.py b/vulkan/scripts/generator_common.py index ef0719db64..ef021f2462 100644 --- a/vulkan/scripts/generator_common.py +++ b/vulkan/scripts/generator_common.py @@ -97,6 +97,9 @@ version_code_list = [] # Dict for mapping a function to the core Vulkan API version. version_dict = {} +# Dict for mapping a promoted instance extension to the core Vulkan API version. +promoted_inst_ext_dict = {} + def indent(num): """Returns the requested indents. @@ -183,6 +186,15 @@ def version_code(version): return version[11:] +def version_2_api_version(version): + """Returns the api version from a version string. + + Args: + version: Vulkan version string. + """ + return 'VK_API' + version[2:] + + def is_function_supported(cmd): """Returns true if a function is core or from a supportable extension. @@ -327,6 +339,7 @@ def parse_vulkan_registry(): return_type_dict version_code_list version_dict + promoted_inst_ext_dict """ registry = os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'external', 'vulkan-headers', 'registry', 'vk.xml') @@ -379,6 +392,10 @@ def parse_vulkan_registry(): apiversion = '' if extension.tag == 'extension': extname = extension.get('name') + if (extension.get('type') == 'instance' and + extension.get('promotedto') is not None): + promoted_inst_ext_dict[extname] = \ + version_2_api_version(extension.get('promotedto')) for req in extension: if req.get('feature') is not None: apiversion = req.get('feature') |