From 05683f6b6b6eb13dfba66f71194d9ba4c4458c25 Mon Sep 17 00:00:00 2001 From: Charles Giessen Date: Tue, 8 Jun 2021 15:06:28 -0600 Subject: [PATCH] Call KHR version of get phys dev properties if necessary Previously, vk-bootstrap didn't support calling vkGetPhyicalDeviceFeaturesKHR on devices which support the extension. This makes vk-bootstrap more amenable to 1.0 only hardware, like rasberry pi's. --- src/VkBootstrap.cpp | 92 ++++++++++++++++++++++++++++----------------- src/VkBootstrap.h | 19 +++++++--- 2 files changed, 71 insertions(+), 40 deletions(-) diff --git a/src/VkBootstrap.cpp b/src/VkBootstrap.cpp index ac44672..4f0f673 100644 --- a/src/VkBootstrap.cpp +++ b/src/VkBootstrap.cpp @@ -120,7 +120,8 @@ class VulkanFunctions { out_ptr = reinterpret_cast(ptr_vkGetInstanceProcAddr(instance, func_name)); } - template void get_device_proc_addr(VkDevice device, T& out_ptr, const char* func_name) { + template + void get_device_proc_addr(VkDevice device, T& out_ptr, const char* func_name) { out_ptr = reinterpret_cast(fp_vkGetDeviceProcAddr(device, func_name)); } @@ -136,6 +137,7 @@ class VulkanFunctions { PFN_vkEnumeratePhysicalDevices fp_vkEnumeratePhysicalDevices = nullptr; PFN_vkGetPhysicalDeviceFeatures fp_vkGetPhysicalDeviceFeatures = nullptr; PFN_vkGetPhysicalDeviceFeatures2 fp_vkGetPhysicalDeviceFeatures2 = nullptr; + PFN_vkGetPhysicalDeviceFeatures2KHR fp_vkGetPhysicalDeviceFeatures2KHR = nullptr; PFN_vkGetPhysicalDeviceFormatProperties fp_vkGetPhysicalDeviceFormatProperties = nullptr; PFN_vkGetPhysicalDeviceImageFormatProperties fp_vkGetPhysicalDeviceImageFormatProperties = nullptr; PFN_vkGetPhysicalDeviceProperties fp_vkGetPhysicalDeviceProperties = nullptr; @@ -169,6 +171,7 @@ class VulkanFunctions { get_inst_proc_addr(fp_vkEnumeratePhysicalDevices, "vkEnumeratePhysicalDevices"); get_inst_proc_addr(fp_vkGetPhysicalDeviceFeatures, "vkGetPhysicalDeviceFeatures"); get_inst_proc_addr(fp_vkGetPhysicalDeviceFeatures2, "vkGetPhysicalDeviceFeatures2"); + get_inst_proc_addr(fp_vkGetPhysicalDeviceFeatures2KHR, "vkGetPhysicalDeviceFeatures2KHR"); get_inst_proc_addr(fp_vkGetPhysicalDeviceFormatProperties, "vkGetPhysicalDeviceFormatProperties"); get_inst_proc_addr(fp_vkGetPhysicalDeviceImageFormatProperties, "vkGetPhysicalDeviceImageFormatProperties"); get_inst_proc_addr(fp_vkGetPhysicalDeviceProperties, "vkGetPhysicalDeviceProperties"); @@ -615,6 +618,10 @@ detail::Result InstanceBuilder::build() const { if (info.debug_callback != nullptr && system.debug_utils_available) { extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); } + if (detail::check_extension_supported( + system.available_extensions, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) { + extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + } if (!info.headless_context) { auto check_add_window_ext = [&](const char* name) -> bool { @@ -978,8 +985,7 @@ uint32_t get_present_queue_index(VkPhysicalDevice const phys_device, } // namespace detail -PhysicalDeviceSelector::PhysicalDeviceDesc PhysicalDeviceSelector::populate_device_details(uint32_t instance_version, - VkPhysicalDevice phys_device, +PhysicalDeviceSelector::PhysicalDeviceDesc PhysicalDeviceSelector::populate_device_details(VkPhysicalDevice phys_device, std::vector const& src_extended_features_chain) const { PhysicalDeviceSelector::PhysicalDeviceDesc desc{}; desc.phys_device = phys_device; @@ -993,10 +999,14 @@ PhysicalDeviceSelector::PhysicalDeviceDesc PhysicalDeviceSelector::populate_devi #if defined(VK_API_VERSION_1_1) desc.device_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; +#else + desc.device_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; +#endif auto fill_chain = src_extended_features_chain; - if (!fill_chain.empty() && instance_version >= VK_API_VERSION_1_1) { + if (!fill_chain.empty() && + (instance_info.version >= VK_API_VERSION_1_1 || instance_info.supports_properties2_ext)) { detail::GenericFeaturesPNextNode* prev = nullptr; for (auto& extension : fill_chain) { @@ -1006,15 +1016,26 @@ PhysicalDeviceSelector::PhysicalDeviceDesc PhysicalDeviceSelector::populate_devi prev = &extension; } +#if defined(VK_API_VERSION_1_1) VkPhysicalDeviceFeatures2 local_features{}; local_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; local_features.pNext = &fill_chain.front(); - - detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2(phys_device, &local_features); + if (desc.device_properties.apiVersion >= VK_API_VERSION_1_1) { + detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2(phys_device, &local_features); + } else if (instance_info.supports_properties2_ext) { + detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2KHR(phys_device, &local_features); + } +#else + VkPhysicalDeviceFeatures2KHR local_features{}; + local_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + local_features.pNext = &fill_chain.front(); + if (instance_info.supports_properties2_ext) { + detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2KHR(phys_device, &local_features); + } +#endif + desc.extended_features_chain = fill_chain; } - desc.extended_features_chain = fill_chain; -#endif return desc; } @@ -1116,6 +1137,10 @@ PhysicalDeviceSelector::PhysicalDeviceSelector(Instance const& instance) { criteria.require_present = !instance.headless; criteria.required_version = instance.instance_version; criteria.desired_version = instance.instance_version; + detail::get_vector( + instance_info.extensions, detail::vulkan_functions().fp_vkEnumerateInstanceExtensionProperties, nullptr); + instance_info.supports_properties2_ext = detail::check_extension_supported( + instance_info.extensions, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); } detail::Result PhysicalDeviceSelector::select() const { @@ -1125,6 +1150,8 @@ detail::Result PhysicalDeviceSelector::select() const { } + + std::vector physical_devices; auto physical_devices_ret = detail::get_vector( @@ -1139,8 +1166,7 @@ detail::Result PhysicalDeviceSelector::select() const { std::vector phys_device_descriptions; for (auto& phys_device : physical_devices) { - phys_device_descriptions.push_back(populate_device_details( - instance_info.version, phys_device, criteria.extended_features_chain)); + phys_device_descriptions.push_back(populate_device_details(phys_device, criteria.extended_features_chain)); } PhysicalDeviceDesc selected_device{}; @@ -1471,12 +1497,10 @@ detail::Result DeviceBuilder::build() const { device.queue_families = physical_device.queue_families; device.allocation_callbacks = info.allocation_callbacks; device.fp_vkGetDeviceProcAddr = detail::vulkan_functions().fp_vkGetDeviceProcAddr; - detail::vulkan_functions().get_device_proc_addr(device.device, - device.internal_table.fp_vkGetDeviceQueue, - "vkGetDeviceQueue"); - detail::vulkan_functions().get_device_proc_addr(device.device, - device.internal_table.fp_vkDestroyDevice, - "vkDestroyDevice"); + detail::vulkan_functions().get_device_proc_addr( + device.device, device.internal_table.fp_vkGetDeviceQueue, "vkGetDeviceQueue"); + detail::vulkan_functions().get_device_proc_addr( + device.device, device.internal_table.fp_vkDestroyDevice, "vkDestroyDevice"); return device; } DeviceBuilder& DeviceBuilder::custom_queue_setup(std::vector queue_descriptions) { @@ -1607,7 +1631,8 @@ VkExtent2D find_extent(VkSurfaceCapabilitiesKHR const& capabilities, uint32_t de void destroy_swapchain(Swapchain const& swapchain) { if (swapchain.device != VK_NULL_HANDLE && swapchain.swapchain != VK_NULL_HANDLE) { - swapchain.internal_table.fp_vkDestroySwapchainKHR(swapchain.device, swapchain.swapchain, swapchain.allocation_callbacks); + swapchain.internal_table.fp_vkDestroySwapchainKHR( + swapchain.device, swapchain.swapchain, swapchain.allocation_callbacks); } } @@ -1724,27 +1749,25 @@ detail::Result SwapchainBuilder::build() const { swapchain_create_info.clipped = info.clipped; swapchain_create_info.oldSwapchain = info.old_swapchain; Swapchain swapchain{}; - PFN_vkCreateSwapchainKHR swapchain_create_proc; - detail::vulkan_functions().get_device_proc_addr(info.device, swapchain_create_proc, "vkCreateSwapchainKHR"); - auto res = swapchain_create_proc(info.device, &swapchain_create_info, info.allocation_callbacks, &swapchain.swapchain); -; if (res != VK_SUCCESS) { + PFN_vkCreateSwapchainKHR swapchain_create_proc; + detail::vulkan_functions().get_device_proc_addr(info.device, swapchain_create_proc, "vkCreateSwapchainKHR"); + auto res = swapchain_create_proc( + info.device, &swapchain_create_info, info.allocation_callbacks, &swapchain.swapchain); + ; + if (res != VK_SUCCESS) { return detail::Error{ SwapchainError::failed_create_swapchain, res }; } swapchain.device = info.device; swapchain.image_format = surface_format.format; swapchain.extent = extent; - detail::vulkan_functions().get_device_proc_addr(info.device, - swapchain.internal_table.fp_vkGetSwapchainImagesKHR, - "vkGetSwapchainImagesKHR"); - detail::vulkan_functions().get_device_proc_addr(info.device, - swapchain.internal_table.fp_vkCreateImageView, - "vkCreateImageView"); - detail::vulkan_functions().get_device_proc_addr(info.device, - swapchain.internal_table.fp_vkDestroyImageView, - "vkDestroyImageView"); - detail::vulkan_functions().get_device_proc_addr(info.device, - swapchain.internal_table.fp_vkDestroySwapchainKHR, - "vkDestroySwapchainKHR"); + detail::vulkan_functions().get_device_proc_addr( + info.device, swapchain.internal_table.fp_vkGetSwapchainImagesKHR, "vkGetSwapchainImagesKHR"); + detail::vulkan_functions().get_device_proc_addr( + info.device, swapchain.internal_table.fp_vkCreateImageView, "vkCreateImageView"); + detail::vulkan_functions().get_device_proc_addr( + info.device, swapchain.internal_table.fp_vkDestroyImageView, "vkDestroyImageView"); + detail::vulkan_functions().get_device_proc_addr( + info.device, swapchain.internal_table.fp_vkDestroySwapchainKHR, "vkDestroySwapchainKHR"); auto images = swapchain.get_images(); if (!images) { return detail::Error{ SwapchainError::failed_get_swapchain_images }; @@ -1787,7 +1810,8 @@ detail::Result> Swapchain::get_image_views() { createInfo.subresourceRange.baseArrayLayer = 0; createInfo.subresourceRange.layerCount = 1; - VkResult res = internal_table.fp_vkCreateImageView(device, &createInfo, allocation_callbacks, &views[i]); + VkResult res = + internal_table.fp_vkCreateImageView(device, &createInfo, allocation_callbacks, &views[i]); if (res != VK_SUCCESS) return detail::Error{ SwapchainError::failed_create_swapchain_image_views, res }; } diff --git a/src/VkBootstrap.h b/src/VkBootstrap.h index 9403411..e276838 100644 --- a/src/VkBootstrap.h +++ b/src/VkBootstrap.h @@ -474,7 +474,9 @@ class PhysicalDeviceSelector { VkInstance instance = VK_NULL_HANDLE; VkSurfaceKHR surface = VK_NULL_HANDLE; uint32_t version = VK_MAKE_VERSION(1, 0, 0); + std::vector extensions; bool headless = false; + bool supports_properties2_ext = false; } instance_info; struct PhysicalDeviceDesc { @@ -484,17 +486,20 @@ class PhysicalDeviceSelector { VkPhysicalDeviceFeatures device_features{}; VkPhysicalDeviceProperties device_properties{}; VkPhysicalDeviceMemoryProperties mem_properties{}; + +// Because the KHR version is a typedef in Vulkan 1.1, it is safe to define one or the other. #if defined(VK_API_VERSION_1_1) VkPhysicalDeviceFeatures2 device_features2{}; - std::vector extended_features_chain; +#else + VkPhysicalDeviceFeatures2KHR device_features2{}; #endif + std::vector extended_features_chain; }; // We copy the extension features stored in the selector criteria under the prose of a // "template" to ensure that after fetching everything is compared 1:1 during a match. - PhysicalDeviceDesc populate_device_details(uint32_t instance_version, - VkPhysicalDevice phys_device, + PhysicalDeviceDesc populate_device_details(VkPhysicalDevice phys_device, std::vector const& src_extended_features_chain) const; struct SelectionCriteria { @@ -556,6 +561,7 @@ struct Device { // Return a loaded dispatch table DispatchTable make_table() const; + private: struct { PFN_vkGetDeviceQueue fp_vkGetDeviceQueue = nullptr; @@ -622,11 +628,12 @@ struct Swapchain { // VkImageViews must be destroyed. detail::Result> get_image_views(); void destroy_image_views(std::vector const& image_views); + private: struct { - PFN_vkGetSwapchainImagesKHR fp_vkGetSwapchainImagesKHR = nullptr; - PFN_vkCreateImageView fp_vkCreateImageView = nullptr; - PFN_vkDestroyImageView fp_vkDestroyImageView = nullptr; + PFN_vkGetSwapchainImagesKHR fp_vkGetSwapchainImagesKHR = nullptr; + PFN_vkCreateImageView fp_vkCreateImageView = nullptr; + PFN_vkDestroyImageView fp_vkDestroyImageView = nullptr; PFN_vkDestroySwapchainKHR fp_vkDestroySwapchainKHR = nullptr; } internal_table; friend class SwapchainBuilder;