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.
This commit is contained in:
Charles Giessen 2024-06-13 10:02:11 -05:00 committed by Charles Giessen
parent fa75546109
commit 71a29a4b72
3 changed files with 39 additions and 6 deletions

View File

@ -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 // Should only be false if extension_supported was unable to be filled out, due to the
// physical device not supporting vkGetPhysicalDeviceFeatures2 in any capacity. // physical device not supporting vkGetPhysicalDeviceFeatures2 in any capacity.
if (extension_requested.nodes.size() != nodes.size()) { if (extension_requested.nodes.size() != nodes.size()) {
@ -67,6 +67,21 @@ bool GenericFeatureChain::match(GenericFeatureChain const& extension_requested)
return true; 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 { void GenericFeatureChain::chain_up(VkPhysicalDeviceFeatures2& feats2) noexcept {
detail::GenericFeaturesPNextNode* prev = nullptr; detail::GenericFeaturesPNextNode* prev = nullptr;
for (auto& extension : nodes) { for (auto& extension : nodes) {
@ -1030,8 +1045,7 @@ bool supports_features(const VkPhysicalDeviceFeatures& supported,
if (requested.variableMultisampleRate && !supported.variableMultisampleRate) return false; if (requested.variableMultisampleRate && !supported.variableMultisampleRate) return false;
if (requested.inheritedQueries && !supported.inheritedQueries) return false; if (requested.inheritedQueries && !supported.inheritedQueries) return false;
return extension_supported.match_all(extension_requested);
return extension_supported.match(extension_requested);
} }
// clang-format on // clang-format on
// Finds the first queue which supports the desired operations. Returns QUEUE_INDEX_MAX_VALUE if none is found // 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; detail::GenericFeatureChain requested_features;
requested_features.nodes.push_back(node); 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) { 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); fill_chain.chain_up(actual_pdf2);
detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2(physical_device, &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) { if (required_features_supported) {
extended_features_chain.combine(requested_features); extended_features_chain.combine(requested_features);
} }

View File

@ -194,7 +194,8 @@ struct GenericFeatureChain {
nodes.push_back(features); 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; void chain_up(VkPhysicalDeviceFeatures2& feats2) noexcept;

View File

@ -632,6 +632,8 @@ TEST_CASE("Querying Required Extension Features", "[VkBootstrap.select_features]
.select(); .select();
REQUIRE(phys_dev_ret.has_value()); 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()); vkb::DeviceBuilder device_builder(phys_dev_ret.value());
auto device_ret = device_builder.build(); auto device_ret = device_builder.build();
REQUIRE(device_ret.has_value()); REQUIRE(device_ret.has_value());
@ -783,6 +785,13 @@ TEST_CASE("Querying Required Extension Features in 1.1", "[VkBootstrap.version]"
.select(); .select();
REQUIRE(phys_dev_ret.has_value()); 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()); vkb::DeviceBuilder device_builder(phys_dev_ret.value());
auto device_ret = device_builder.build(); auto device_ret = device_builder.build();
REQUIRE(device_ret.has_value()); REQUIRE(device_ret.has_value());
@ -800,6 +809,13 @@ TEST_CASE("Querying Required Extension Features in 1.1", "[VkBootstrap.version]"
.select(); .select();
REQUIRE(phys_dev_ret.has_value()); 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{}; VkPhysicalDeviceFeatures2 phys_dev_feats2{};
phys_dev_feats2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; phys_dev_feats2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
phys_dev_feats2.pNext = reinterpret_cast<void*>(&descriptor_indexing_features); phys_dev_feats2.pNext = reinterpret_cast<void*>(&descriptor_indexing_features);
@ -822,6 +838,8 @@ TEST_CASE("Querying Required Extension Features in 1.1", "[VkBootstrap.version]"
.select(); .select();
REQUIRE(phys_dev_ret.has_value()); REQUIRE(phys_dev_ret.has_value());
REQUIRE(phys_dev_ret.value().are_extension_features_present(descriptor_indexing_features));
VkPhysicalDeviceFeatures2 phys_dev_feats2{}; VkPhysicalDeviceFeatures2 phys_dev_feats2{};
phys_dev_feats2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; phys_dev_feats2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
phys_dev_feats2.pNext = reinterpret_cast<void*>(&descriptor_indexing_features); phys_dev_feats2.pNext = reinterpret_cast<void*>(&descriptor_indexing_features);