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.
This commit is contained in:
Charles Giessen 2021-06-08 15:06:28 -06:00 committed by Charles Giessen
parent f955777c8a
commit 05683f6b6b
2 changed files with 71 additions and 40 deletions

View File

@ -120,7 +120,8 @@ class VulkanFunctions {
out_ptr = reinterpret_cast<T>(ptr_vkGetInstanceProcAddr(instance, func_name)); out_ptr = reinterpret_cast<T>(ptr_vkGetInstanceProcAddr(instance, func_name));
} }
template <typename T> void get_device_proc_addr(VkDevice device, T& out_ptr, const char* func_name) { template <typename T>
void get_device_proc_addr(VkDevice device, T& out_ptr, const char* func_name) {
out_ptr = reinterpret_cast<T>(fp_vkGetDeviceProcAddr(device, func_name)); out_ptr = reinterpret_cast<T>(fp_vkGetDeviceProcAddr(device, func_name));
} }
@ -136,6 +137,7 @@ class VulkanFunctions {
PFN_vkEnumeratePhysicalDevices fp_vkEnumeratePhysicalDevices = nullptr; PFN_vkEnumeratePhysicalDevices fp_vkEnumeratePhysicalDevices = nullptr;
PFN_vkGetPhysicalDeviceFeatures fp_vkGetPhysicalDeviceFeatures = nullptr; PFN_vkGetPhysicalDeviceFeatures fp_vkGetPhysicalDeviceFeatures = nullptr;
PFN_vkGetPhysicalDeviceFeatures2 fp_vkGetPhysicalDeviceFeatures2 = nullptr; PFN_vkGetPhysicalDeviceFeatures2 fp_vkGetPhysicalDeviceFeatures2 = nullptr;
PFN_vkGetPhysicalDeviceFeatures2KHR fp_vkGetPhysicalDeviceFeatures2KHR = nullptr;
PFN_vkGetPhysicalDeviceFormatProperties fp_vkGetPhysicalDeviceFormatProperties = nullptr; PFN_vkGetPhysicalDeviceFormatProperties fp_vkGetPhysicalDeviceFormatProperties = nullptr;
PFN_vkGetPhysicalDeviceImageFormatProperties fp_vkGetPhysicalDeviceImageFormatProperties = nullptr; PFN_vkGetPhysicalDeviceImageFormatProperties fp_vkGetPhysicalDeviceImageFormatProperties = nullptr;
PFN_vkGetPhysicalDeviceProperties fp_vkGetPhysicalDeviceProperties = nullptr; PFN_vkGetPhysicalDeviceProperties fp_vkGetPhysicalDeviceProperties = nullptr;
@ -169,6 +171,7 @@ class VulkanFunctions {
get_inst_proc_addr(fp_vkEnumeratePhysicalDevices, "vkEnumeratePhysicalDevices"); get_inst_proc_addr(fp_vkEnumeratePhysicalDevices, "vkEnumeratePhysicalDevices");
get_inst_proc_addr(fp_vkGetPhysicalDeviceFeatures, "vkGetPhysicalDeviceFeatures"); get_inst_proc_addr(fp_vkGetPhysicalDeviceFeatures, "vkGetPhysicalDeviceFeatures");
get_inst_proc_addr(fp_vkGetPhysicalDeviceFeatures2, "vkGetPhysicalDeviceFeatures2"); 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_vkGetPhysicalDeviceFormatProperties, "vkGetPhysicalDeviceFormatProperties");
get_inst_proc_addr(fp_vkGetPhysicalDeviceImageFormatProperties, "vkGetPhysicalDeviceImageFormatProperties"); get_inst_proc_addr(fp_vkGetPhysicalDeviceImageFormatProperties, "vkGetPhysicalDeviceImageFormatProperties");
get_inst_proc_addr(fp_vkGetPhysicalDeviceProperties, "vkGetPhysicalDeviceProperties"); get_inst_proc_addr(fp_vkGetPhysicalDeviceProperties, "vkGetPhysicalDeviceProperties");
@ -615,6 +618,10 @@ detail::Result<Instance> InstanceBuilder::build() const {
if (info.debug_callback != nullptr && system.debug_utils_available) { if (info.debug_callback != nullptr && system.debug_utils_available) {
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); 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) { if (!info.headless_context) {
auto check_add_window_ext = [&](const char* name) -> bool { 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 } // namespace detail
PhysicalDeviceSelector::PhysicalDeviceDesc PhysicalDeviceSelector::populate_device_details(uint32_t instance_version, PhysicalDeviceSelector::PhysicalDeviceDesc PhysicalDeviceSelector::populate_device_details(VkPhysicalDevice phys_device,
VkPhysicalDevice phys_device,
std::vector<detail::GenericFeaturesPNextNode> const& src_extended_features_chain) const { std::vector<detail::GenericFeaturesPNextNode> const& src_extended_features_chain) const {
PhysicalDeviceSelector::PhysicalDeviceDesc desc{}; PhysicalDeviceSelector::PhysicalDeviceDesc desc{};
desc.phys_device = phys_device; desc.phys_device = phys_device;
@ -993,10 +999,14 @@ PhysicalDeviceSelector::PhysicalDeviceDesc PhysicalDeviceSelector::populate_devi
#if defined(VK_API_VERSION_1_1) #if defined(VK_API_VERSION_1_1)
desc.device_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; 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; 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; detail::GenericFeaturesPNextNode* prev = nullptr;
for (auto& extension : fill_chain) { for (auto& extension : fill_chain) {
@ -1006,15 +1016,26 @@ PhysicalDeviceSelector::PhysicalDeviceDesc PhysicalDeviceSelector::populate_devi
prev = &extension; prev = &extension;
} }
#if defined(VK_API_VERSION_1_1)
VkPhysicalDeviceFeatures2 local_features{}; VkPhysicalDeviceFeatures2 local_features{};
local_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; local_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
local_features.pNext = &fill_chain.front(); local_features.pNext = &fill_chain.front();
if (desc.device_properties.apiVersion >= VK_API_VERSION_1_1) {
detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2(phys_device, &local_features); 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; return desc;
} }
@ -1116,6 +1137,10 @@ PhysicalDeviceSelector::PhysicalDeviceSelector(Instance const& instance) {
criteria.require_present = !instance.headless; criteria.require_present = !instance.headless;
criteria.required_version = instance.instance_version; criteria.required_version = instance.instance_version;
criteria.desired_version = instance.instance_version; criteria.desired_version = instance.instance_version;
detail::get_vector<VkExtensionProperties>(
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<PhysicalDevice> PhysicalDeviceSelector::select() const { detail::Result<PhysicalDevice> PhysicalDeviceSelector::select() const {
@ -1125,6 +1150,8 @@ detail::Result<PhysicalDevice> PhysicalDeviceSelector::select() const {
} }
std::vector<VkPhysicalDevice> physical_devices; std::vector<VkPhysicalDevice> physical_devices;
auto physical_devices_ret = detail::get_vector<VkPhysicalDevice>( auto physical_devices_ret = detail::get_vector<VkPhysicalDevice>(
@ -1139,8 +1166,7 @@ detail::Result<PhysicalDevice> PhysicalDeviceSelector::select() const {
std::vector<PhysicalDeviceDesc> phys_device_descriptions; std::vector<PhysicalDeviceDesc> phys_device_descriptions;
for (auto& phys_device : physical_devices) { for (auto& phys_device : physical_devices) {
phys_device_descriptions.push_back(populate_device_details( phys_device_descriptions.push_back(populate_device_details(phys_device, criteria.extended_features_chain));
instance_info.version, phys_device, criteria.extended_features_chain));
} }
PhysicalDeviceDesc selected_device{}; PhysicalDeviceDesc selected_device{};
@ -1471,12 +1497,10 @@ detail::Result<Device> DeviceBuilder::build() const {
device.queue_families = physical_device.queue_families; device.queue_families = physical_device.queue_families;
device.allocation_callbacks = info.allocation_callbacks; device.allocation_callbacks = info.allocation_callbacks;
device.fp_vkGetDeviceProcAddr = detail::vulkan_functions().fp_vkGetDeviceProcAddr; device.fp_vkGetDeviceProcAddr = detail::vulkan_functions().fp_vkGetDeviceProcAddr;
detail::vulkan_functions().get_device_proc_addr(device.device, detail::vulkan_functions().get_device_proc_addr(
device.internal_table.fp_vkGetDeviceQueue, device.device, device.internal_table.fp_vkGetDeviceQueue, "vkGetDeviceQueue");
"vkGetDeviceQueue"); detail::vulkan_functions().get_device_proc_addr(
detail::vulkan_functions().get_device_proc_addr(device.device, device.device, device.internal_table.fp_vkDestroyDevice, "vkDestroyDevice");
device.internal_table.fp_vkDestroyDevice,
"vkDestroyDevice");
return device; return device;
} }
DeviceBuilder& DeviceBuilder::custom_queue_setup(std::vector<CustomQueueDescription> queue_descriptions) { DeviceBuilder& DeviceBuilder::custom_queue_setup(std::vector<CustomQueueDescription> queue_descriptions) {
@ -1607,7 +1631,8 @@ VkExtent2D find_extent(VkSurfaceCapabilitiesKHR const& capabilities, uint32_t de
void destroy_swapchain(Swapchain const& swapchain) { void destroy_swapchain(Swapchain const& swapchain) {
if (swapchain.device != VK_NULL_HANDLE && swapchain.swapchain != VK_NULL_HANDLE) { 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);
} }
} }
@ -1726,25 +1751,23 @@ detail::Result<Swapchain> SwapchainBuilder::build() const {
Swapchain swapchain{}; Swapchain swapchain{};
PFN_vkCreateSwapchainKHR swapchain_create_proc; PFN_vkCreateSwapchainKHR swapchain_create_proc;
detail::vulkan_functions().get_device_proc_addr(info.device, swapchain_create_proc, "vkCreateSwapchainKHR"); 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); auto res = swapchain_create_proc(
; if (res != VK_SUCCESS) { info.device, &swapchain_create_info, info.allocation_callbacks, &swapchain.swapchain);
;
if (res != VK_SUCCESS) {
return detail::Error{ SwapchainError::failed_create_swapchain, res }; return detail::Error{ SwapchainError::failed_create_swapchain, res };
} }
swapchain.device = info.device; swapchain.device = info.device;
swapchain.image_format = surface_format.format; swapchain.image_format = surface_format.format;
swapchain.extent = extent; swapchain.extent = extent;
detail::vulkan_functions().get_device_proc_addr(info.device, detail::vulkan_functions().get_device_proc_addr(
swapchain.internal_table.fp_vkGetSwapchainImagesKHR, info.device, swapchain.internal_table.fp_vkGetSwapchainImagesKHR, "vkGetSwapchainImagesKHR");
"vkGetSwapchainImagesKHR"); detail::vulkan_functions().get_device_proc_addr(
detail::vulkan_functions().get_device_proc_addr(info.device, info.device, swapchain.internal_table.fp_vkCreateImageView, "vkCreateImageView");
swapchain.internal_table.fp_vkCreateImageView, detail::vulkan_functions().get_device_proc_addr(
"vkCreateImageView"); info.device, swapchain.internal_table.fp_vkDestroyImageView, "vkDestroyImageView");
detail::vulkan_functions().get_device_proc_addr(info.device, detail::vulkan_functions().get_device_proc_addr(
swapchain.internal_table.fp_vkDestroyImageView, info.device, swapchain.internal_table.fp_vkDestroySwapchainKHR, "vkDestroySwapchainKHR");
"vkDestroyImageView");
detail::vulkan_functions().get_device_proc_addr(info.device,
swapchain.internal_table.fp_vkDestroySwapchainKHR,
"vkDestroySwapchainKHR");
auto images = swapchain.get_images(); auto images = swapchain.get_images();
if (!images) { if (!images) {
return detail::Error{ SwapchainError::failed_get_swapchain_images }; return detail::Error{ SwapchainError::failed_get_swapchain_images };
@ -1787,7 +1810,8 @@ detail::Result<std::vector<VkImageView>> Swapchain::get_image_views() {
createInfo.subresourceRange.baseArrayLayer = 0; createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1; 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) if (res != VK_SUCCESS)
return detail::Error{ SwapchainError::failed_create_swapchain_image_views, res }; return detail::Error{ SwapchainError::failed_create_swapchain_image_views, res };
} }

View File

@ -474,7 +474,9 @@ class PhysicalDeviceSelector {
VkInstance instance = VK_NULL_HANDLE; VkInstance instance = VK_NULL_HANDLE;
VkSurfaceKHR surface = VK_NULL_HANDLE; VkSurfaceKHR surface = VK_NULL_HANDLE;
uint32_t version = VK_MAKE_VERSION(1, 0, 0); uint32_t version = VK_MAKE_VERSION(1, 0, 0);
std::vector<VkExtensionProperties> extensions;
bool headless = false; bool headless = false;
bool supports_properties2_ext = false;
} instance_info; } instance_info;
struct PhysicalDeviceDesc { struct PhysicalDeviceDesc {
@ -484,17 +486,20 @@ class PhysicalDeviceSelector {
VkPhysicalDeviceFeatures device_features{}; VkPhysicalDeviceFeatures device_features{};
VkPhysicalDeviceProperties device_properties{}; VkPhysicalDeviceProperties device_properties{};
VkPhysicalDeviceMemoryProperties mem_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) #if defined(VK_API_VERSION_1_1)
VkPhysicalDeviceFeatures2 device_features2{}; VkPhysicalDeviceFeatures2 device_features2{};
std::vector<detail::GenericFeaturesPNextNode> extended_features_chain; #else
VkPhysicalDeviceFeatures2KHR device_features2{};
#endif #endif
std::vector<detail::GenericFeaturesPNextNode> extended_features_chain;
}; };
// We copy the extension features stored in the selector criteria under the prose of a // 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. // "template" to ensure that after fetching everything is compared 1:1 during a match.
PhysicalDeviceDesc populate_device_details(uint32_t instance_version, PhysicalDeviceDesc populate_device_details(VkPhysicalDevice phys_device,
VkPhysicalDevice phys_device,
std::vector<detail::GenericFeaturesPNextNode> const& src_extended_features_chain) const; std::vector<detail::GenericFeaturesPNextNode> const& src_extended_features_chain) const;
struct SelectionCriteria { struct SelectionCriteria {
@ -556,6 +561,7 @@ struct Device {
// Return a loaded dispatch table // Return a loaded dispatch table
DispatchTable make_table() const; DispatchTable make_table() const;
private: private:
struct { struct {
PFN_vkGetDeviceQueue fp_vkGetDeviceQueue = nullptr; PFN_vkGetDeviceQueue fp_vkGetDeviceQueue = nullptr;
@ -622,6 +628,7 @@ struct Swapchain {
// VkImageViews must be destroyed. // VkImageViews must be destroyed.
detail::Result<std::vector<VkImageView>> get_image_views(); detail::Result<std::vector<VkImageView>> get_image_views();
void destroy_image_views(std::vector<VkImageView> const& image_views); void destroy_image_views(std::vector<VkImageView> const& image_views);
private: private:
struct { struct {
PFN_vkGetSwapchainImagesKHR fp_vkGetSwapchainImagesKHR = nullptr; PFN_vkGetSwapchainImagesKHR fp_vkGetSwapchainImagesKHR = nullptr;