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.
This commit is contained in:
Charles Giessen 2023-10-22 14:33:47 -06:00 committed by Charles Giessen
parent f9717f66bb
commit 9e36810a48
3 changed files with 52 additions and 22 deletions

View File

@ -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<std::vector<PhysicalDevice>> 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<VkQueueFamilyProperties> PhysicalDevice::get_queue_families() const { return queue_families; }
std::vector<std::string> PhysicalDevice::get_extensions() const { return extensions; }
std::vector<std::string> PhysicalDevice::get_extensions() const { return extensions_to_enable; }
std::vector<std::string> 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<Device> DeviceBuilder::build() const {
queueCreateInfos.push_back(queue_create_info);
}
std::vector<const char*> extensions;
for (const auto& ext : physical_device.extensions) {
extensions.push_back(ext.c_str());
std::vector<const char*> 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<VkBaseOutStructure*> final_pnext_chain;
VkDeviceCreateInfo device_create_info = {};
@ -1526,8 +1540,8 @@ Result<Device> DeviceBuilder::build() const {
device_create_info.flags = info.flags;
device_create_info.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
device_create_info.pQueueCreateInfos = queueCreateInfos.data();
device_create_info.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
device_create_info.ppEnabledExtensionNames = extensions.data();
device_create_info.enabledExtensionCount = static_cast<uint32_t>(extensions_to_enable.size());
device_create_info.ppEnabledExtensionNames = extensions_to_enable.data();
Device device;

View File

@ -495,16 +495,24 @@ struct PhysicalDevice {
// Query the list of extensions which should be enabled
std::vector<std::string> get_extensions() const;
// Query the list of extensions which the physical device supports
std::vector<std::string> 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<std::string> extensions;
std::vector<std::string> extensions_to_enable;
std::vector<std::string> available_extensions;
std::vector<VkQueueFamilyProperties> queue_families;
std::vector<detail::GenericFeaturesPNextNode> 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);

View File

@ -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);