Make Vulkan 1.1 Headers required

Previously, the code tried to make it possible to use vk-bootstrap with
Vulkan 1.0 headers. This makes the code complicated and left several paths
completly untested. Making Vulkan 1.1 headers allows for simpler code.

Note: This does NOT make a Vulkan 1.1 capable driver required to use
vk-bootstrap. This only requires that the headers used to build
vk-bootstrap are 1.1 or above.
This commit is contained in:
Charles Giessen 2023-01-12 15:33:10 -07:00 committed by Charles Giessen
parent 932b7794ac
commit 8e61b2d81c
3 changed files with 30 additions and 55 deletions

View File

@ -76,13 +76,13 @@ See `example/triangle.cpp` for an example that renders a triangle to the screen.
## Setting up `vk-bootstrap` ## Setting up `vk-bootstrap`
This library has no external dependencies beyond C++14, its standard library, and the Vulkan Headers. This library has no external dependencies beyond C++14, its standard library, and at least the 1.1 version of the Vulkan Headers.
Note: on Unix platforms, `vk-bootstrap` will require the dynamic linker in order to compile as the library doesn't link against `vulkan-1.dll`/`libvulkan.so` directly. Note: on Unix platforms, `vk-bootstrap` will require the dynamic linker in order to compile as the library doesn't link against `vulkan-1.dll`/`libvulkan.so` directly.
### Copy-Paste ### Copy-Paste
Copy the `src/VkBootstrap.h` and `src/VkBootstrap.cpp` files into your project, include them into your build, then compile as you normally would. Copy the `src/VkBootstrap.h`, `src/VkBootstrapDispatch.h`, and `src/VkBootstrap.cpp` files into your project, include them into your build, then compile as you normally would.
`vk-bootstrap` is *not* a header only library, so no need to worry about macros in the header. `vk-bootstrap` is *not* a header only library, so no need to worry about macros in the header.

View File

@ -587,11 +587,11 @@ 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);
} }
bool properties2_ext_enabled = false; bool properties2_ext_enabled =
if (detail::check_extension_supported(system.available_extensions, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) && api_version < VKB_VK_API_VERSION_1_1 && detail::check_extension_supported(system.available_extensions,
api_version < VKB_VK_API_VERSION_1_1) { VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
if (properties2_ext_enabled) {
extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
properties2_ext_enabled = true;
} }
#if defined(VK_KHR_portability_enumeration) #if defined(VK_KHR_portability_enumeration)
@ -1010,14 +1010,14 @@ PhysicalDevice PhysicalDeviceSelector::populate_device_details(VkPhysicalDevice
for (const auto& ext : available_extensions) { for (const auto& ext : available_extensions) {
physical_device.extensions.push_back(&ext.extensionName[0]); physical_device.extensions.push_back(&ext.extensionName[0]);
} }
#if defined(VK_KHR_get_physical_device_properties2)
physical_device.features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; // same value as the non-KHR version physical_device.features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; // same value as the non-KHR version
#endif
physical_device.properties2_ext_enabled = instance_info.properties2_ext_enabled; physical_device.properties2_ext_enabled = instance_info.properties2_ext_enabled;
auto fill_chain = src_extended_features_chain; auto fill_chain = src_extended_features_chain;
if (!fill_chain.empty() && (instance_info.version >= VKB_VK_API_VERSION_1_1 || instance_info.properties2_ext_enabled)) { bool instance_is_1_1 = instance_info.version >= VKB_VK_API_VERSION_1_1;
if (!fill_chain.empty() && (instance_is_1_1 || instance_info.properties2_ext_enabled)) {
detail::GenericFeaturesPNextNode* prev = nullptr; detail::GenericFeaturesPNextNode* prev = nullptr;
for (auto& extension : fill_chain) { for (auto& extension : fill_chain) {
@ -1027,29 +1027,15 @@ PhysicalDevice PhysicalDeviceSelector::populate_device_details(VkPhysicalDevice
prev = &extension; prev = &extension;
} }
bool phys_dev_is_1_1 = instance_info.version >= VKB_VK_API_VERSION_1_1 &&
physical_device.properties.apiVersion >= VKB_VK_API_VERSION_1_1;
#if defined(VKB_VK_API_VERSION_1_1)
if (phys_dev_is_1_1 || instance_info.properties2_ext_enabled) {
VkPhysicalDeviceFeatures2 local_features{}; VkPhysicalDeviceFeatures2 local_features{};
local_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; // KHR is same as core here local_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; // KHR is same as core here
local_features.pNext = &fill_chain.front(); local_features.pNext = &fill_chain.front();
// Use KHR function if not able to use the core function // Use KHR function if not able to use the core function
if (!phys_dev_is_1_1) { if (instance_is_1_1) {
detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2KHR(vk_phys_device, &local_features);
} else {
detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2(vk_phys_device, &local_features); detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2(vk_phys_device, &local_features);
} else {
detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2KHR(vk_phys_device, &local_features);
} }
}
#elif defined(VK_KHR_get_physical_device_properties2)
if (instance_info.properties2_ext_enabled) {
VkPhysicalDeviceFeatures2KHR local_features_khr{};
local_features_khr.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
local_features_khr.pNext = &fill_chain.front();
detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2KHR(vk_phys_device, &local_features_khr);
}
#endif
physical_device.extended_features_chain = fill_chain; physical_device.extended_features_chain = fill_chain;
} }
@ -1496,7 +1482,6 @@ Result<Device> DeviceBuilder::build() const {
std::vector<VkBaseOutStructure*> final_pnext_chain; std::vector<VkBaseOutStructure*> final_pnext_chain;
VkDeviceCreateInfo device_create_info = {}; VkDeviceCreateInfo device_create_info = {};
#if defined(VK_KHR_get_physical_device_properties2)
bool user_defined_phys_dev_features_2 = false; bool user_defined_phys_dev_features_2 = false;
for (auto& pnext : info.pNext_chain) { for (auto& pnext : info.pNext_chain) {
if (pnext->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2) { if (pnext->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2) {
@ -1526,7 +1511,6 @@ Result<Device> DeviceBuilder::build() const {
device_create_info.pEnabledFeatures = &physical_device.features; device_create_info.pEnabledFeatures = &physical_device.features;
} }
} }
#endif
for (auto& pnext : info.pNext_chain) { for (auto& pnext : info.pNext_chain) {
final_pnext_chain.push_back(pnext); final_pnext_chain.push_back(pnext);
@ -1877,7 +1861,6 @@ Result<std::vector<VkImageView>> Swapchain::get_image_views(const void* pNext) {
if (!swapchain_images_ret) return swapchain_images_ret.error(); if (!swapchain_images_ret) return swapchain_images_ret.error();
const auto swapchain_images = swapchain_images_ret.value(); const auto swapchain_images = swapchain_images_ret.value();
#if defined(VK_VERSION_1_1)
bool already_contains_image_view_usage = false; bool already_contains_image_view_usage = false;
while (pNext) { while (pNext) {
if (reinterpret_cast<const VkBaseInStructure*>(pNext)->sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO) { if (reinterpret_cast<const VkBaseInStructure*>(pNext)->sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO) {
@ -1890,20 +1873,17 @@ Result<std::vector<VkImageView>> Swapchain::get_image_views(const void* pNext) {
desired_flags.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO; desired_flags.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO;
desired_flags.pNext = pNext; desired_flags.pNext = pNext;
desired_flags.usage = image_usage_flags; desired_flags.usage = image_usage_flags;
#endif
std::vector<VkImageView> views(swapchain_images.size()); std::vector<VkImageView> views(swapchain_images.size());
for (size_t i = 0; i < swapchain_images.size(); i++) { for (size_t i = 0; i < swapchain_images.size(); i++) {
VkImageViewCreateInfo createInfo = {}; VkImageViewCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
#if defined(VK_VERSION_1_1)
if (instance_version >= VKB_VK_API_VERSION_1_1 && !already_contains_image_view_usage) { if (instance_version >= VKB_VK_API_VERSION_1_1 && !already_contains_image_view_usage) {
createInfo.pNext = &desired_flags; createInfo.pNext = &desired_flags;
} else { } else {
createInfo.pNext = pNext; createInfo.pNext = pNext;
} }
#else
createInfo.pNext = pNext;
#endif
createInfo.image = swapchain_images[i]; createInfo.image = swapchain_images[i];
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = image_format; createInfo.format = image_format;

View File

@ -501,11 +501,8 @@ struct PhysicalDevice {
std::vector<std::string> extensions; std::vector<std::string> extensions;
std::vector<VkQueueFamilyProperties> queue_families; std::vector<VkQueueFamilyProperties> queue_families;
std::vector<detail::GenericFeaturesPNextNode> extended_features_chain; std::vector<detail::GenericFeaturesPNextNode> extended_features_chain;
#if defined(VKB_VK_API_VERSION_1_1)
VkPhysicalDeviceFeatures2 features2{}; VkPhysicalDeviceFeatures2 features2{};
#else
VkPhysicalDeviceFeatures2KHR features2{};
#endif
bool defer_surface_initialization = false; bool defer_surface_initialization = false;
bool properties2_ext_enabled = false; bool properties2_ext_enabled = false;
enum class Suitable { yes, partial, no }; enum class Suitable { yes, partial, no };
@ -598,12 +595,11 @@ class PhysicalDeviceSelector {
// Require a physical device which supports a specific set of general/extension features. // Require a physical device which supports a specific set of general/extension features.
// If this function is used, the user should not put their own VkPhysicalDeviceFeatures2 in // If this function is used, the user should not put their own VkPhysicalDeviceFeatures2 in
// the pNext chain of VkDeviceCreateInfo. // the pNext chain of VkDeviceCreateInfo.
#if defined(VKB_VK_API_VERSION_1_1)
template <typename T> PhysicalDeviceSelector& add_required_extension_features(T const& features) { template <typename T> PhysicalDeviceSelector& add_required_extension_features(T const& features) {
criteria.extended_features_chain.push_back(features); criteria.extended_features_chain.push_back(features);
return *this; return *this;
} }
#endif
// Require a physical device which supports the features in VkPhysicalDeviceFeatures. // Require a physical device which supports the features in VkPhysicalDeviceFeatures.
PhysicalDeviceSelector& set_required_features(VkPhysicalDeviceFeatures const& features); PhysicalDeviceSelector& set_required_features(VkPhysicalDeviceFeatures const& features);
#if defined(VKB_VK_API_VERSION_1_2) #if defined(VKB_VK_API_VERSION_1_2)
@ -659,9 +655,8 @@ class PhysicalDeviceSelector {
uint32_t desired_version = VKB_VK_API_VERSION_1_0; uint32_t desired_version = VKB_VK_API_VERSION_1_0;
VkPhysicalDeviceFeatures required_features{}; VkPhysicalDeviceFeatures required_features{};
#if defined(VK_KHR_get_physical_device_properties2) VkPhysicalDeviceFeatures2 required_features2{};
VkPhysicalDeviceFeatures2KHR required_features2{};
#endif
std::vector<detail::GenericFeaturesPNextNode> extended_features_chain; std::vector<detail::GenericFeaturesPNextNode> extended_features_chain;
bool defer_surface_initialization = false; bool defer_surface_initialization = false;
bool use_first_gpu_unconditionally = false; bool use_first_gpu_unconditionally = false;