From 9e36810a4805a2411d96f83a8f5fa482c1281694 Mon Sep 17 00:00:00 2001 From: Charles Giessen Date: Sun, 22 Oct 2023 14:33:47 -0600 Subject: [PATCH] Add enable_extension_if_present to vkb::PhysicalDevice If the given extension is present, enable_extension_if_present will make the extension be enabled on the device. This fixes a gap in capability due to the deprecation of add_desired_extension. --- src/VkBootstrap.cpp | 54 ++++++++++++++++++++++++--------------- src/VkBootstrap.h | 12 +++++++-- tests/bootstrap_tests.cpp | 8 ++++++ 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/src/VkBootstrap.cpp b/src/VkBootstrap.cpp index 774e2bb..1d908ea 100644 --- a/src/VkBootstrap.cpp +++ b/src/VkBootstrap.cpp @@ -1005,7 +1005,7 @@ PhysicalDevice PhysicalDeviceSelector::populate_device_details(VkPhysicalDevice available_extensions, detail::vulkan_functions().fp_vkEnumerateDeviceExtensionProperties, vk_phys_device, nullptr); if (available_extensions_ret != VK_SUCCESS) return physical_device; for (const auto& ext : available_extensions) { - physical_device.extensions.push_back(&ext.extensionName[0]); + physical_device.available_extensions.push_back(&ext.extensionName[0]); } physical_device.features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; // same value as the non-KHR version @@ -1066,11 +1066,12 @@ PhysicalDevice::Suitable PhysicalDeviceSelector::is_device_suitable(PhysicalDevi if (criteria.require_present && !present_queue && !criteria.defer_surface_initialization) return PhysicalDevice::Suitable::no; - auto required_extensions_supported = detail::check_device_extension_support(pd.extensions, criteria.required_extensions); + auto required_extensions_supported = + detail::check_device_extension_support(pd.available_extensions, criteria.required_extensions); if (required_extensions_supported.size() != criteria.required_extensions.size()) return PhysicalDevice::Suitable::no; - auto desired_extensions_supported = detail::check_device_extension_support(pd.extensions, criteria.desired_extensions); + auto desired_extensions_supported = detail::check_device_extension_support(pd.available_extensions, criteria.desired_extensions); if (desired_extensions_supported.size() != criteria.desired_extensions.size()) suitable = PhysicalDevice::Suitable::partial; @@ -1160,19 +1161,20 @@ Result> PhysicalDeviceSelector::select_impl(DeviceSe phys_dev.features = criteria.required_features; phys_dev.extended_features_chain = criteria.extended_features_chain; bool portability_ext_available = false; - for (const auto& ext : phys_dev.extensions) + for (const auto& ext : phys_dev.available_extensions) if (criteria.enable_portability_subset && ext == "VK_KHR_portability_subset") portability_ext_available = true; - auto desired_extensions_supported = detail::check_device_extension_support(phys_dev.extensions, criteria.desired_extensions); + auto desired_extensions_supported = + detail::check_device_extension_support(phys_dev.available_extensions, criteria.desired_extensions); - phys_dev.extensions.clear(); - phys_dev.extensions.insert( - phys_dev.extensions.end(), criteria.required_extensions.begin(), criteria.required_extensions.end()); - phys_dev.extensions.insert( - phys_dev.extensions.end(), desired_extensions_supported.begin(), desired_extensions_supported.end()); + phys_dev.extensions_to_enable.clear(); + phys_dev.extensions_to_enable.insert( + phys_dev.extensions_to_enable.end(), criteria.required_extensions.begin(), criteria.required_extensions.end()); + phys_dev.extensions_to_enable.insert( + phys_dev.extensions_to_enable.end(), desired_extensions_supported.begin(), desired_extensions_supported.end()); if (portability_ext_available) { - phys_dev.extensions.push_back("VK_KHR_portability_subset"); + phys_dev.extensions_to_enable.push_back("VK_KHR_portability_subset"); } }; @@ -1368,12 +1370,24 @@ bool PhysicalDevice::has_separate_transfer_queue() const { return detail::get_separate_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT) != detail::QUEUE_INDEX_MAX_VALUE; } std::vector PhysicalDevice::get_queue_families() const { return queue_families; } -std::vector PhysicalDevice::get_extensions() const { return extensions; } +std::vector PhysicalDevice::get_extensions() const { return extensions_to_enable; } +std::vector PhysicalDevice::get_available_extensions() const { return available_extensions; } bool PhysicalDevice::is_extension_present(const char* ext) const { - return std::find_if(std::begin(extensions), std::end(extensions), [ext](std::string const& ext_name) { + return std::find_if(std::begin(available_extensions), std::end(available_extensions), [ext](std::string const& ext_name) { return ext_name == ext; - }) != std::end(extensions); + }) != std::end(available_extensions); } +bool PhysicalDevice::enable_extension_if_present(const char* extension) { + auto it = std::find_if(std::begin(available_extensions), + std::end(available_extensions), + [extension](std::string const& ext_name) { return ext_name == extension; }); + if (it != std::end(available_extensions)) { + extensions_to_enable.push_back(extension); + return true; + } + return false; +} + PhysicalDevice::operator VkPhysicalDevice() const { return this->physical_device; } // ---- Queues ---- // @@ -1472,12 +1486,12 @@ Result DeviceBuilder::build() const { queueCreateInfos.push_back(queue_create_info); } - std::vector extensions; - for (const auto& ext : physical_device.extensions) { - extensions.push_back(ext.c_str()); + std::vector extensions_to_enable; + for (const auto& ext : physical_device.extensions_to_enable) { + extensions_to_enable.push_back(ext.c_str()); } if (physical_device.surface != VK_NULL_HANDLE || physical_device.defer_surface_initialization) - extensions.push_back({ VK_KHR_SWAPCHAIN_EXTENSION_NAME }); + extensions_to_enable.push_back({ VK_KHR_SWAPCHAIN_EXTENSION_NAME }); std::vector final_pnext_chain; VkDeviceCreateInfo device_create_info = {}; @@ -1526,8 +1540,8 @@ Result DeviceBuilder::build() const { device_create_info.flags = info.flags; device_create_info.queueCreateInfoCount = static_cast(queueCreateInfos.size()); device_create_info.pQueueCreateInfos = queueCreateInfos.data(); - device_create_info.enabledExtensionCount = static_cast(extensions.size()); - device_create_info.ppEnabledExtensionNames = extensions.data(); + device_create_info.enabledExtensionCount = static_cast(extensions_to_enable.size()); + device_create_info.ppEnabledExtensionNames = extensions_to_enable.data(); Device device; diff --git a/src/VkBootstrap.h b/src/VkBootstrap.h index f2eb2b9..91a17a3 100644 --- a/src/VkBootstrap.h +++ b/src/VkBootstrap.h @@ -495,16 +495,24 @@ struct PhysicalDevice { // Query the list of extensions which should be enabled std::vector get_extensions() const; + // Query the list of extensions which the physical device supports + std::vector get_available_extensions() const; + // Returns true if an extension should be enabled on the device bool is_extension_present(const char* extension) const; + // If the given extension is present, make the extension be enabled on the device. + // Returns true the extension is present. + bool enable_extension_if_present(const char* extension); + // A conversion function which allows this PhysicalDevice to be used // in places where VkPhysicalDevice would have been used. operator VkPhysicalDevice() const; private: uint32_t instance_version = VKB_VK_API_VERSION_1_0; - std::vector extensions; + std::vector extensions_to_enable; + std::vector available_extensions; std::vector queue_families; std::vector extended_features_chain; VkPhysicalDeviceFeatures2 features2{}; @@ -575,7 +583,7 @@ class PhysicalDeviceSelector { // Require a memory heap from VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT with `size` memory available. PhysicalDeviceSelector& required_device_memory_size(VkDeviceSize size); // Prefer a memory heap from VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT with `size` memory available. - PhysicalDeviceSelector& desired_device_memory_size(VkDeviceSize size); + [[deprecated]] PhysicalDeviceSelector& desired_device_memory_size(VkDeviceSize size); // Require a physical device which supports a specific extension. PhysicalDeviceSelector& add_required_extension(const char* extension); diff --git a/tests/bootstrap_tests.cpp b/tests/bootstrap_tests.cpp index fb08dc6..b080a1d 100644 --- a/tests/bootstrap_tests.cpp +++ b/tests/bootstrap_tests.cpp @@ -73,6 +73,7 @@ TEST_CASE("Instance with surface", "[VkBootstrap.bootstrap]") { mock.physical_devices_details[0].properties.apiVersion = VK_API_VERSION_1_1; mock.physical_devices_details[0].extensions.push_back(get_extension_properties("VK_KHR_multiview")); mock.physical_devices_details[0].extensions.push_back(get_extension_properties("VK_KHR_driver_properties")); + mock.physical_devices_details[0].extensions.push_back(get_extension_properties("VK_EXT_robustness2")); auto surface = mock.get_new_surface(get_basic_surface_details()); GIVEN("A window and a vulkan instance") { @@ -116,6 +117,13 @@ TEST_CASE("Instance with surface", "[VkBootstrap.bootstrap]") { REQUIRE(phys_dev_ret->is_extension_present(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME)); REQUIRE(!phys_dev_ret->is_extension_present(VK_KHR_16BIT_STORAGE_EXTENSION_NAME)); + + REQUIRE(phys_dev_ret->enable_extension_if_present(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME)); + REQUIRE(!phys_dev_ret->enable_extension_if_present(VK_KHR_16BIT_STORAGE_EXTENSION_NAME)); + + auto device_ret = vkb::DeviceBuilder(phys_dev_ret.value()).build(); + REQUIRE(device_ret.has_value()); + vkb::destroy_device(device_ret.value()); } vkb::destroy_surface(instance, surface);