mirror of
https://github.com/charles-lunarg/vk-bootstrap.git
synced 2024-11-26 00:34:35 +00:00
Add VulkanFeatureConfig, mechanism to select pre-made configs
This makes it easy to enable a set of features, extensions, and a Vulkan Version that are pre-defined.
This commit is contained in:
parent
8922a41bd4
commit
d6d63121e9
@ -1227,6 +1227,15 @@ PhysicalDeviceSelector& PhysicalDeviceSelector::allow_any_gpu_device_type(bool a
|
||||
criteria.allow_any_type = allow_any_type;
|
||||
return *this;
|
||||
}
|
||||
PhysicalDeviceSelector& PhysicalDeviceSelector::set_vulkan_feature_config(VulkanFeatureConfig& feature_config) {
|
||||
set_minimum_version(feature_config.api_major_version, feature_config.api_minor_version);
|
||||
require_present(feature_config.require_presentation);
|
||||
add_required_extensions(feature_config.required_extensions);
|
||||
set_required_features(feature_config.features_1_0);
|
||||
set_required_features_11(feature_config.features_1_1);
|
||||
set_required_features_12(feature_config.features_1_2);
|
||||
return *this;
|
||||
}
|
||||
PhysicalDeviceSelector& PhysicalDeviceSelector::require_present(bool require) {
|
||||
criteria.require_present = require;
|
||||
return *this;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "VkBootstrapDispatch.h"
|
||||
#include "VulkanFeatureConfig.h"
|
||||
|
||||
namespace vkb {
|
||||
|
||||
@ -444,6 +445,11 @@ class PhysicalDeviceSelector {
|
||||
// Allow selection of a gpu device type that isn't the preferred physical device type. Defaults to true.
|
||||
PhysicalDeviceSelector& allow_any_gpu_device_type(bool allow_any_type = true);
|
||||
|
||||
// Sets the "Vulkan Feature Config" to use when selecting a VkPhysicalDevice.
|
||||
// A Feature Config is a pre defined collection of extensions, features, and properties that are
|
||||
// required to be supported. For more information, go to `VulkanFeatureConfig.h`
|
||||
PhysicalDeviceSelector& set_vulkan_feature_config(VulkanFeatureConfig& feature_config);
|
||||
|
||||
// Require that a physical device supports presentation. Defaults to true.
|
||||
PhysicalDeviceSelector& require_present(bool require = true);
|
||||
|
||||
|
205
src/VulkanFeatureConfig.h
Normal file
205
src/VulkanFeatureConfig.h
Normal file
@ -0,0 +1,205 @@
|
||||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
/*
|
||||
The VulkanFeatureConfig mechanism of vk-bootstrap provides an easy way to select a VkPhysicalDevice based off of list of pre-made
|
||||
configurations that specify the required version, features, extensions, and properties.
|
||||
*/
|
||||
|
||||
|
||||
namespace vkb {
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct StructureWrapper {
|
||||
template <typename T> StructureWrapper(T const& structure) noexcept {
|
||||
T* ptr = new T();
|
||||
*ptr = structure;
|
||||
pStructure = reinterpret_cast<VkBaseOutStructure*>(ptr);
|
||||
}
|
||||
~StructureWrapper() noexcept { delete pStructure; }
|
||||
StructureWrapper(StructureWrapper const&) = delete;
|
||||
StructureWrapper& operator=(StructureWrapper const&) = delete;
|
||||
StructureWrapper(StructureWrapper&& other) noexcept : pStructure(other.pStructure) {
|
||||
other.pStructure = nullptr;
|
||||
}
|
||||
StructureWrapper& operator=(StructureWrapper&& other) noexcept {
|
||||
delete pStructure;
|
||||
pStructure = other.pStructure;
|
||||
other.pStructure = nullptr;
|
||||
return *this;
|
||||
}
|
||||
VkBaseOutStructure* pStructure = nullptr;
|
||||
};
|
||||
|
||||
inline VkPhysicalDeviceFeatures get_common_1_0_features() {
|
||||
VkPhysicalDeviceFeatures features{};
|
||||
features.fullDrawIndexUint32 = true;
|
||||
features.imageCubeArray = true;
|
||||
features.independentBlend = true;
|
||||
features.geometryShader = true;
|
||||
features.tessellationShader = true;
|
||||
features.sampleRateShading = true;
|
||||
features.dualSrcBlend = true;
|
||||
features.logicOp = true;
|
||||
features.multiDrawIndirect = true;
|
||||
features.drawIndirectFirstInstance = true;
|
||||
features.depthClamp = true;
|
||||
features.depthBiasClamp = true;
|
||||
features.fillModeNonSolid = true;
|
||||
features.wideLines = true;
|
||||
features.largePoints = true;
|
||||
features.multiViewport = true;
|
||||
features.samplerAnisotropy = true;
|
||||
features.pipelineStatisticsQuery = true;
|
||||
features.textureCompressionBC = true;
|
||||
features.occlusionQueryPrecise = true;
|
||||
features.vertexPipelineStoresAndAtomics = true;
|
||||
features.fragmentStoresAndAtomics = true;
|
||||
features.shaderTessellationAndGeometryPointSize = true;
|
||||
features.shaderImageGatherExtended = true;
|
||||
features.shaderStorageImageExtendedFormats = true;
|
||||
features.shaderStorageImageWriteWithoutFormat = true;
|
||||
features.shaderUniformBufferArrayDynamicIndexing = true;
|
||||
features.shaderSampledImageArrayDynamicIndexing = true;
|
||||
features.shaderStorageBufferArrayDynamicIndexing = true;
|
||||
features.shaderStorageImageArrayDynamicIndexing = true;
|
||||
features.shaderClipDistance = true;
|
||||
features.shaderCullDistance = true;
|
||||
features.variableMultisampleRate = true;
|
||||
return features;
|
||||
}
|
||||
|
||||
inline VkPhysicalDeviceVulkan11Features get_common_1_1_features() {
|
||||
VkPhysicalDeviceVulkan11Features features;
|
||||
features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
|
||||
features.storageBuffer16BitAccess = true;
|
||||
features.uniformAndStorageBuffer16BitAccess = true;
|
||||
features.multiview = true;
|
||||
features.multiviewTessellationShader = true;
|
||||
features.variablePointersStorageBuffer = true;
|
||||
features.variablePointers = true;
|
||||
features.shaderDrawParameters = true;
|
||||
return features;
|
||||
}
|
||||
|
||||
inline VkPhysicalDeviceVulkan12Features get_common_1_2_features() {
|
||||
VkPhysicalDeviceVulkan12Features features{};
|
||||
features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
|
||||
features.samplerMirrorClampToEdge = true;
|
||||
features.drawIndirectCount = true;
|
||||
features.descriptorIndexing = true;
|
||||
features.scalarBlockLayout = true;
|
||||
features.imagelessFramebuffer = true;
|
||||
features.uniformBufferStandardLayout = true;
|
||||
features.shaderSubgroupExtendedTypes = true;
|
||||
features.separateDepthStencilLayouts = true;
|
||||
features.hostQueryReset = true;
|
||||
features.timelineSemaphore = true;
|
||||
features.bufferDeviceAddress = true;
|
||||
features.subgroupBroadcastDynamicId = true;
|
||||
return features;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
/*
|
||||
Stores all the possible versions, features, extensions, and properties for a VulkanFeatureConfig
|
||||
*/
|
||||
struct VulkanFeatureConfig {
|
||||
VulkanFeatureConfig() {
|
||||
features_1_1.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
|
||||
features_1_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
|
||||
}
|
||||
uint32_t api_major_version = 1;
|
||||
uint32_t api_minor_version = 0;
|
||||
bool require_presentation = true;
|
||||
|
||||
std::vector<const char*> required_extensions;
|
||||
|
||||
VkPhysicalDeviceFeatures features_1_0{};
|
||||
VkPhysicalDeviceVulkan11Features features_1_1{};
|
||||
VkPhysicalDeviceVulkan12Features features_1_2{};
|
||||
|
||||
VkPhysicalDeviceProperties properties_1_0{};
|
||||
};
|
||||
|
||||
/*
|
||||
Configuration for commonly available features in Vulkan 1.0 devices
|
||||
*/
|
||||
|
||||
static VulkanFeatureConfig& get_feature_config_vulkan_1_0_desktop() {
|
||||
static VulkanFeatureConfig config{};
|
||||
config.features_1_0 = detail::get_common_1_0_features();
|
||||
return config;
|
||||
}
|
||||
|
||||
/*
|
||||
Configuration for commonly available features in Vulkan 1.1 devices
|
||||
*/
|
||||
static VulkanFeatureConfig& get_feature_config_vulkan_1_1_desktop() {
|
||||
static VulkanFeatureConfig config{};
|
||||
config.api_minor_version = 1;
|
||||
config.features_1_0 = detail::get_common_1_0_features();
|
||||
config.features_1_1 = detail::get_common_1_1_features();
|
||||
return config;
|
||||
}
|
||||
|
||||
/*
|
||||
Configuration for commonly available features in Vulkan 1.2 devices
|
||||
*/
|
||||
static VulkanFeatureConfig& get_feature_config_vulkan_1_2_desktop() {
|
||||
static VulkanFeatureConfig config{};
|
||||
config.api_minor_version = 2;
|
||||
config.features_1_0 = detail::get_common_1_0_features();
|
||||
config.features_1_1 = detail::get_common_1_1_features();
|
||||
config.features_1_2 = detail::get_common_1_2_features();
|
||||
return config;
|
||||
}
|
||||
|
||||
/*
|
||||
Configuration that requests features available only found in the most recent hardware
|
||||
*/
|
||||
static VulkanFeatureConfig& get_feature_config_bleeding_edge_desktop() {
|
||||
static VulkanFeatureConfig config{};
|
||||
config.api_minor_version = 2;
|
||||
config.required_extensions.push_back("VK_KHR_deferred_host_operations");
|
||||
config.required_extensions.push_back("VK_KHR_acceleration_structure");
|
||||
config.required_extensions.push_back("VK_KHR_ray_query");
|
||||
config.required_extensions.push_back("VK_KHR_pipeline_library");
|
||||
config.required_extensions.push_back("VK_KHR_ray_tracing_pipeline");
|
||||
config.required_extensions.push_back("VK_KHR_fragment_shading_rate");
|
||||
config.features_1_0 = detail::get_common_1_0_features();
|
||||
config.features_1_1 = detail::get_common_1_1_features();
|
||||
config.features_1_2 = detail::get_common_1_2_features();
|
||||
return config;
|
||||
}
|
||||
|
||||
static VulkanFeatureConfig& get_feature_config_vulkan_1_0_mobile() {
|
||||
static VulkanFeatureConfig config{};
|
||||
return config;
|
||||
}
|
||||
|
||||
static VulkanFeatureConfig& get_feature_config_vulkan_1_1_mobile() {
|
||||
static VulkanFeatureConfig config{};
|
||||
config.api_minor_version = 1;
|
||||
return config;
|
||||
}
|
||||
|
||||
static VulkanFeatureConfig& get_feature_config_vulkan_1_2_mobile() {
|
||||
static VulkanFeatureConfig config{};
|
||||
config.api_minor_version = 2;
|
||||
return config;
|
||||
}
|
||||
|
||||
static VulkanFeatureConfig& get_feature_config_virtual_reality_base() {
|
||||
static VulkanFeatureConfig config{};
|
||||
config.api_minor_version = 1;
|
||||
config.features_1_0 = detail::get_common_1_0_features();
|
||||
config.features_1_1 = detail::get_common_1_1_features();
|
||||
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
} // namespace vkb
|
@ -1,4 +1,4 @@
|
||||
add_executable(vk-bootstrap-test main.cpp bootstrap_tests.cpp error_code_tests.cpp unit_tests.cpp)
|
||||
add_executable(vk-bootstrap-test main.cpp bootstrap_tests.cpp error_code_tests.cpp unit_tests.cpp feature_config.cpp)
|
||||
target_link_libraries(vk-bootstrap-test
|
||||
PRIVATE
|
||||
vk-bootstrap
|
||||
|
@ -20,18 +20,18 @@
|
||||
|
||||
#include "../src/VkBootstrap.h"
|
||||
|
||||
GLFWwindow* create_window_glfw(const char* window_name = "", bool resize = true) {
|
||||
inline GLFWwindow* create_window_glfw(const char* window_name = "", bool resize = true) {
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
if (!resize) glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||
|
||||
return glfwCreateWindow(1024, 1024, window_name, NULL, NULL);
|
||||
}
|
||||
void destroy_window_glfw(GLFWwindow* window) {
|
||||
inline void destroy_window_glfw(GLFWwindow* window) {
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
}
|
||||
VkSurfaceKHR create_surface_glfw(
|
||||
inline VkSurfaceKHR create_surface_glfw(
|
||||
VkInstance instance, GLFWwindow* window, VkAllocationCallbacks* allocator = nullptr) {
|
||||
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
||||
VkResult err = glfwCreateWindowSurface(instance, window, allocator, &surface);
|
||||
@ -48,6 +48,12 @@ VkSurfaceKHR create_surface_glfw(
|
||||
return surface;
|
||||
}
|
||||
|
||||
inline void destroy_surface(vkb::Instance& instance_ret, VkSurfaceKHR surface) {
|
||||
PFN_vkDestroySurfaceKHR fp_vkDestroySurfaceKHR = reinterpret_cast<PFN_vkDestroySurfaceKHR>(
|
||||
instance_ret.fp_vkGetInstanceProcAddr(instance_ret.instance, "vkDestroySurfaceKHR"));
|
||||
fp_vkDestroySurfaceKHR(instance_ret.instance, surface, nullptr);
|
||||
}
|
||||
|
||||
struct VulkanLibrary {
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
void* library;
|
||||
|
35
tests/feature_config.cpp
Normal file
35
tests/feature_config.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
#include "common.h"
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
TEST_CASE("TargetBaseVulkanDesktop", "[VkBootstrap.feature_config]") {
|
||||
|
||||
auto window = create_window_glfw("Instance with surface");
|
||||
vkb::InstanceBuilder instance_builder;
|
||||
auto instance_ret = instance_builder.use_default_debug_messenger().request_validation_layers().build();
|
||||
REQUIRE(instance_ret);
|
||||
vkb::Instance instance = instance_ret.value();
|
||||
auto surface = create_surface_glfw(instance.instance, window);
|
||||
GIVEN("A window and a vulkan instance") {
|
||||
vkb::PhysicalDeviceSelector selector(instance);
|
||||
auto phys_dev_ret = selector.set_surface(surface)
|
||||
.set_vulkan_feature_config(vkb::get_feature_config_vulkan_1_0_desktop())
|
||||
.select();
|
||||
REQUIRE(phys_dev_ret);
|
||||
|
||||
GIVEN("A physical device created with the TargetBaseVulkanDesktop") {
|
||||
vkb::DeviceBuilder device_builder(phys_dev_ret.value());
|
||||
auto device_ret = device_builder.build();
|
||||
REQUIRE(device_ret);
|
||||
vkb::Device device = device_ret.value();
|
||||
|
||||
// possible swapchain creation...
|
||||
|
||||
vkb::destroy_device(device);
|
||||
}
|
||||
}
|
||||
|
||||
destroy_surface(*instance_ret, surface);
|
||||
vkb::destroy_instance(instance);
|
||||
destroy_window_glfw(window);
|
||||
}
|
Loading…
Reference in New Issue
Block a user