From 71a29a4b72d9d1c4b7d046b8c4bae8efd6d6beaa Mon Sep 17 00:00:00 2001 From: Charles Giessen Date: Thu, 13 Jun 2024 10:02:11 -0500 Subject: [PATCH] Make are_extension_features_present handle mismatched lists The original implementation only worked if the requested features had the same length. It'll now handle that properly. --- src/VkBootstrap.cpp | 24 +++++++++++++++++++----- src/VkBootstrap.h | 3 ++- tests/bootstrap_tests.cpp | 18 ++++++++++++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/VkBootstrap.cpp b/src/VkBootstrap.cpp index c34b95a..313ff48 100644 --- a/src/VkBootstrap.cpp +++ b/src/VkBootstrap.cpp @@ -54,7 +54,7 @@ void GenericFeaturesPNextNode::combine(GenericFeaturesPNextNode const& right) no } } -bool GenericFeatureChain::match(GenericFeatureChain const& extension_requested) const noexcept { +bool GenericFeatureChain::match_all(GenericFeatureChain const& extension_requested) const noexcept { // Should only be false if extension_supported was unable to be filled out, due to the // physical device not supporting vkGetPhysicalDeviceFeatures2 in any capacity. if (extension_requested.nodes.size() != nodes.size()) { @@ -67,6 +67,21 @@ bool GenericFeatureChain::match(GenericFeatureChain const& extension_requested) return true; } +bool GenericFeatureChain::find_and_match(GenericFeatureChain const& extensions_requested) const noexcept { + for (const auto& requested_extension_node : extensions_requested.nodes) { + bool found = false; + for (const auto& supported_node : nodes) { + if (supported_node.sType == requested_extension_node.sType) { + found = true; + if (!GenericFeaturesPNextNode::match(requested_extension_node, supported_node)) return false; + break; + } + } + if (!found) return false; + } + return true; +} + void GenericFeatureChain::chain_up(VkPhysicalDeviceFeatures2& feats2) noexcept { detail::GenericFeaturesPNextNode* prev = nullptr; for (auto& extension : nodes) { @@ -1030,8 +1045,7 @@ bool supports_features(const VkPhysicalDeviceFeatures& supported, if (requested.variableMultisampleRate && !supported.variableMultisampleRate) return false; if (requested.inheritedQueries && !supported.inheritedQueries) return false; - - return extension_supported.match(extension_requested); + return extension_supported.match_all(extension_requested); } // clang-format on // Finds the first queue which supports the desired operations. Returns QUEUE_INDEX_MAX_VALUE if none is found @@ -1512,7 +1526,7 @@ bool PhysicalDevice::is_features_node_present(detail::GenericFeaturesPNextNode c detail::GenericFeatureChain requested_features; requested_features.nodes.push_back(node); - return extended_features_chain.match(requested_features); + return extended_features_chain.find_and_match(requested_features); } bool PhysicalDevice::enable_features_node_if_present(detail::GenericFeaturesPNextNode const& node) { @@ -1529,7 +1543,7 @@ bool PhysicalDevice::enable_features_node_if_present(detail::GenericFeaturesPNex fill_chain.chain_up(actual_pdf2); detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2(physical_device, &actual_pdf2); - bool required_features_supported = fill_chain.match(requested_features); + bool required_features_supported = fill_chain.match_all(requested_features); if (required_features_supported) { extended_features_chain.combine(requested_features); } diff --git a/src/VkBootstrap.h b/src/VkBootstrap.h index 28dbab5..2c6f298 100644 --- a/src/VkBootstrap.h +++ b/src/VkBootstrap.h @@ -194,7 +194,8 @@ struct GenericFeatureChain { nodes.push_back(features); } - bool match(GenericFeatureChain const& extension_requested) const noexcept; + bool match_all(GenericFeatureChain const& extension_requested) const noexcept; + bool find_and_match(GenericFeatureChain const& extension_requested) const noexcept; void chain_up(VkPhysicalDeviceFeatures2& feats2) noexcept; diff --git a/tests/bootstrap_tests.cpp b/tests/bootstrap_tests.cpp index 0cd4781..e5d3cf5 100644 --- a/tests/bootstrap_tests.cpp +++ b/tests/bootstrap_tests.cpp @@ -632,6 +632,8 @@ TEST_CASE("Querying Required Extension Features", "[VkBootstrap.select_features] .select(); REQUIRE(phys_dev_ret.has_value()); + REQUIRE(phys_dev_ret.value().are_extension_features_present(descriptor_indexing_features)); + vkb::DeviceBuilder device_builder(phys_dev_ret.value()); auto device_ret = device_builder.build(); REQUIRE(device_ret.has_value()); @@ -783,6 +785,13 @@ TEST_CASE("Querying Required Extension Features in 1.1", "[VkBootstrap.version]" .select(); REQUIRE(phys_dev_ret.has_value()); + REQUIRE(phys_dev_ret.value().are_extension_features_present(descriptor_indexing_features)); + + VkPhysicalDeviceASTCDecodeFeaturesEXT astc_features{}; + astc_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT; + astc_features.decodeModeSharedExponent = true; + REQUIRE(!phys_dev_ret.value().are_extension_features_present(astc_features)); + vkb::DeviceBuilder device_builder(phys_dev_ret.value()); auto device_ret = device_builder.build(); REQUIRE(device_ret.has_value()); @@ -800,6 +809,13 @@ TEST_CASE("Querying Required Extension Features in 1.1", "[VkBootstrap.version]" .select(); REQUIRE(phys_dev_ret.has_value()); + REQUIRE(!phys_dev_ret.value().are_extension_features_present(descriptor_indexing_features)); + + VkPhysicalDeviceASTCDecodeFeaturesEXT astc_features{}; + astc_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ASTC_DECODE_FEATURES_EXT; + astc_features.decodeModeSharedExponent = true; + REQUIRE(!phys_dev_ret.value().are_extension_features_present(astc_features)); + VkPhysicalDeviceFeatures2 phys_dev_feats2{}; phys_dev_feats2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; phys_dev_feats2.pNext = reinterpret_cast(&descriptor_indexing_features); @@ -822,6 +838,8 @@ TEST_CASE("Querying Required Extension Features in 1.1", "[VkBootstrap.version]" .select(); REQUIRE(phys_dev_ret.has_value()); + REQUIRE(phys_dev_ret.value().are_extension_features_present(descriptor_indexing_features)); + VkPhysicalDeviceFeatures2 phys_dev_feats2{}; phys_dev_feats2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; phys_dev_feats2.pNext = reinterpret_cast(&descriptor_indexing_features);