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

@ -1,6 +1,6 @@
# `vk-bootstrap`
A utility library that jump starts initialization of Vulkan
A utility library that jump starts initialization of Vulkan
This library simplifies the tedious process of:
@ -76,19 +76,19 @@ See `example/triangle.cpp` for an example that renders a triangle to the screen.
## 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 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.
#### Linux specific
vk-bootstrap will load the required symbols at runtime, which requires that the application is linked to the system dynamic link.
vk-bootstrap will load the required symbols at runtime, which requires that the application is linked to the system dynamic link.
How the dynamic linker is linked into the project depends on the build system in question.
If CMake is being used, link vk-bootstrap with `${CMAKE_DL_LIBS}`.
@ -106,7 +106,7 @@ With CMake, add the subdirectory to include the project
add_subdirectory(vk-bootstrap)
```
Then use `target_link_libraries` to use the library in whichever target needs it.
Then use `target_link_libraries` to use the library in whichever target needs it.
```cmake
target_link_libraries(your_application_name vk-bootstrap::vk-bootstrap)
@ -120,7 +120,7 @@ include(FetchContent)
FetchContent_Declare(
fetch_vk_bootstrap
GIT_REPOSITORY https://github.com/charles-lunarg/vk-bootstrap
GIT_TAG BRANCH_OR_TAG #suggest using a tag so the library doesn't update whenever new commits are pushed to a branch
GIT_TAG BRANCH_OR_TAG #suggest using a tag so the library doesn't update whenever new commits are pushed to a branch
)
FetchContent_MakeAvailable(fetch_vk_bootstrap)
target_link_libraries(your_application_name vk-bootstrap::vk-bootstrap)
@ -151,7 +151,7 @@ cmake ../path/to/your_project/ -DVK_BOOTSTRAP_TEST=ON
### Build Options
| Name | Type | Default Value | Description |
| ---- | --- | ---- | ----- |
| ---- | --- | ---- | ----- |
| `VK_BOOTSTRAP_WERROR` | bool | `OFF` | Enable warnings as errors during compilation. |
| `VK_BOOTSTRAP_TEST` | bool | `OFF` | Enable building of the tests in this project. Will download GLFW and Catch2 automatically if enabled. |
| `VK_BOOTSTRAP_VULKAN_HEADER_DIR` | string | `""` | Optional. Specify the directory that contains the Vulkan Headers. Useful if you are downloading the headers manually and don't want vk-bootstrap to download them itself. |

View File

@ -587,11 +587,11 @@ Result<Instance> InstanceBuilder::build() const {
if (info.debug_callback != nullptr && system.debug_utils_available) {
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
}
bool properties2_ext_enabled = false;
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) {
bool properties2_ext_enabled =
api_version < VKB_VK_API_VERSION_1_1 && detail::check_extension_supported(system.available_extensions,
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);
properties2_ext_enabled = true;
}
#if defined(VK_KHR_portability_enumeration)
@ -1010,14 +1010,14 @@ PhysicalDevice PhysicalDeviceSelector::populate_device_details(VkPhysicalDevice
for (const auto& ext : available_extensions) {
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
#endif
physical_device.features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; // same value as the non-KHR version
physical_device.properties2_ext_enabled = instance_info.properties2_ext_enabled;
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;
for (auto& extension : fill_chain) {
@ -1027,29 +1027,15 @@ PhysicalDevice PhysicalDeviceSelector::populate_device_details(VkPhysicalDevice
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{};
local_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; // KHR is same as core here
local_features.pNext = &fill_chain.front();
// Use KHR function if not able to use the core function
if (!phys_dev_is_1_1) {
detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2KHR(vk_phys_device, &local_features);
} else {
detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2(vk_phys_device, &local_features);
}
VkPhysicalDeviceFeatures2 local_features{};
local_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; // KHR is same as core here
local_features.pNext = &fill_chain.front();
// Use KHR function if not able to use the core function
if (instance_is_1_1) {
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;
}
@ -1496,7 +1482,6 @@ Result<Device> DeviceBuilder::build() const {
std::vector<VkBaseOutStructure*> final_pnext_chain;
VkDeviceCreateInfo device_create_info = {};
#if defined(VK_KHR_get_physical_device_properties2)
bool user_defined_phys_dev_features_2 = false;
for (auto& pnext : info.pNext_chain) {
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;
}
}
#endif
for (auto& pnext : info.pNext_chain) {
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();
const auto swapchain_images = swapchain_images_ret.value();
#if defined(VK_VERSION_1_1)
bool already_contains_image_view_usage = false;
while (pNext) {
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.pNext = pNext;
desired_flags.usage = image_usage_flags;
#endif
std::vector<VkImageView> views(swapchain_images.size());
for (size_t i = 0; i < swapchain_images.size(); i++) {
VkImageViewCreateInfo createInfo = {};
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) {
createInfo.pNext = &desired_flags;
} else {
createInfo.pNext = pNext;
}
#else
createInfo.pNext = pNext;
#endif
createInfo.image = swapchain_images[i];
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = image_format;

View File

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