Loading vulkan/libvulkan/driver.cpp +44 −13 Original line number Diff line number Diff line Loading @@ -141,6 +141,7 @@ class CreateInfoWrapper { }; VkApplicationInfo application_info_; uint32_t sanitized_api_version_; ExtensionFilter extension_filter_; Loading Loading @@ -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, Loading Loading @@ -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>( Loading @@ -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 { Loading Loading @@ -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; 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. Loading Loading @@ -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; 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)); Loading vulkan/libvulkan/driver_gen.cpp +48 −0 Original line number Diff line number Diff line Loading @@ -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 vulkan/libvulkan/driver_gen.h +8 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ #include <vulkan/vulkan.h> #include <bitset> #include <optional> #include <vector> namespace vulkan { namespace driver { Loading Loading @@ -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 Loading vulkan/scripts/driver_generator.py +56 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,8 @@ def gen_h(): #include <vulkan/vulkan.h> #include <bitset> #include <optional> #include <vector> namespace vulkan { namespace driver { Loading Loading @@ -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 Loading Loading @@ -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""") Loading vulkan/scripts/generator_common.py +17 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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. Loading Loading @@ -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') Loading Loading @@ -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') Loading Loading
vulkan/libvulkan/driver.cpp +44 −13 Original line number Diff line number Diff line Loading @@ -141,6 +141,7 @@ class CreateInfoWrapper { }; VkApplicationInfo application_info_; uint32_t sanitized_api_version_; ExtensionFilter extension_filter_; Loading Loading @@ -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, Loading Loading @@ -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>( Loading @@ -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 { Loading Loading @@ -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; 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. Loading Loading @@ -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; 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)); Loading
vulkan/libvulkan/driver_gen.cpp +48 −0 Original line number Diff line number Diff line Loading @@ -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
vulkan/libvulkan/driver_gen.h +8 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ #include <vulkan/vulkan.h> #include <bitset> #include <optional> #include <vector> namespace vulkan { namespace driver { Loading Loading @@ -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 Loading
vulkan/scripts/driver_generator.py +56 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,8 @@ def gen_h(): #include <vulkan/vulkan.h> #include <bitset> #include <optional> #include <vector> namespace vulkan { namespace driver { Loading Loading @@ -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 Loading Loading @@ -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""") Loading
vulkan/scripts/generator_common.py +17 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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. Loading Loading @@ -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') Loading Loading @@ -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') Loading