mirror of
https://github.com/charles-lunarg/vk-bootstrap.git
synced 2024-11-22 07:24:34 +00:00
- Restored removed functions
- Restored pNext chain to device (appends to the end of the ExtentionFeatures chain) - Style changes - Migrated ExtensionFeatures into detail
This commit is contained in:
parent
21e400cfcc
commit
0359ceb3fb
@ -846,8 +846,8 @@ std::vector<const char*> check_device_extension_support(
|
||||
// clang-format off
|
||||
bool supports_features(VkPhysicalDeviceFeatures supported,
|
||||
VkPhysicalDeviceFeatures requested,
|
||||
const std::vector<ExtensionFeatures>& extension_supported,
|
||||
const std::vector<ExtensionFeatures>& extension_requested) {
|
||||
std::vector<ExtensionFeatures> const& extension_supported,
|
||||
std::vector<ExtensionFeatures> const& extension_requested) {
|
||||
if (requested.robustBufferAccess && !supported.robustBufferAccess) return false;
|
||||
if (requested.fullDrawIndexUint32 && !supported.fullDrawIndexUint32) return false;
|
||||
if (requested.imageCubeArray && !supported.imageCubeArray) return false;
|
||||
@ -992,7 +992,7 @@ uint32_t get_present_queue_index(VkPhysicalDevice const phys_device,
|
||||
|
||||
PhysicalDeviceSelector::PhysicalDeviceDesc PhysicalDeviceSelector::populate_device_details(
|
||||
uint32_t instance_version, VkPhysicalDevice phys_device,
|
||||
std::vector<ExtensionFeatures> extension_features_as_template) const {
|
||||
std::vector<detail::ExtensionFeatures> extension_features_as_template) const {
|
||||
PhysicalDeviceSelector::PhysicalDeviceDesc desc{};
|
||||
desc.phys_device = phys_device;
|
||||
auto queue_families = detail::get_vector_noerror<VkQueueFamilyProperties>(
|
||||
@ -1007,7 +1007,7 @@ PhysicalDeviceSelector::PhysicalDeviceDesc PhysicalDeviceSelector::populate_devi
|
||||
desc.device_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
||||
desc.extension_features = extension_features_as_template;
|
||||
if (instance_version >= VK_API_VERSION_1_1) {
|
||||
ExtensionFeatures* prev = nullptr;
|
||||
detail::ExtensionFeatures* prev = nullptr;
|
||||
for(auto& extension : desc.extension_features) {
|
||||
if(prev != nullptr) {
|
||||
prev->structure->pNext = extension.structure;
|
||||
@ -1260,12 +1260,12 @@ PhysicalDeviceSelector& PhysicalDeviceSelector::set_desired_version(uint32_t maj
|
||||
// Just calls add_required_features
|
||||
PhysicalDeviceSelector& PhysicalDeviceSelector::set_required_features_11(
|
||||
VkPhysicalDeviceVulkan11Features const& features_11) {
|
||||
add_required_features(features_11);
|
||||
add_required_extension_features(features_11);
|
||||
return *this;
|
||||
}
|
||||
PhysicalDeviceSelector& PhysicalDeviceSelector::set_required_features_12(
|
||||
VkPhysicalDeviceVulkan12Features const& features_12) {
|
||||
add_required_features(features_12);
|
||||
add_required_extension_features(features_12);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
@ -1401,21 +1401,24 @@ detail::Result<Device> DeviceBuilder::build() const {
|
||||
|
||||
bool has_phys_dev_features_2 = false;
|
||||
|
||||
// Setup the pNexts of all the extension features
|
||||
#if defined(VK_API_VERSION_1_1)
|
||||
// Setup the pNexts of all the extension features
|
||||
std::vector<detail::ExtensionFeatures> match = physical_device.extension_features;
|
||||
VkPhysicalDeviceFeatures2 local_features2{};
|
||||
VkBaseOutStructure* tail = nullptr;
|
||||
if (physical_device.instance_version >= VK_MAKE_VERSION(1, 1, 0) &&
|
||||
physical_device.extension_features.size() > 0) {
|
||||
ExtensionFeatures* prev = nullptr;
|
||||
for(auto& extension : physical_device.extension_features) {
|
||||
match.size() > 0) {
|
||||
detail::ExtensionFeatures* prev = nullptr;
|
||||
for(auto& extension : match) {
|
||||
if(prev != nullptr) {
|
||||
prev->structure->pNext = extension.structure;
|
||||
}
|
||||
prev = &extension;
|
||||
tail = prev->structure;
|
||||
}
|
||||
local_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
||||
local_features2.features = physical_device.features;
|
||||
local_features2.pNext = physical_device.extension_features[0].structure;
|
||||
local_features2.pNext = match.front().structure;
|
||||
has_phys_dev_features_2 = true;
|
||||
}
|
||||
#endif
|
||||
@ -1427,19 +1430,31 @@ detail::Result<Device> DeviceBuilder::build() const {
|
||||
device_create_info.pQueueCreateInfos = queueCreateInfos.data();
|
||||
device_create_info.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
|
||||
device_create_info.ppEnabledExtensionNames = extensions.data();
|
||||
|
||||
detail::setup_pNext_chain(device_create_info, info.pNext_chain);
|
||||
|
||||
#if defined(VK_API_VERSION_1_1)
|
||||
// VUID-VkDeviceCreateInfo-pNext-00373 - don't add pEnabledFeatures if the phys_dev_features_2 is present
|
||||
if (!has_phys_dev_features_2) {
|
||||
device_create_info.pEnabledFeatures = &physical_device.features;
|
||||
} else {
|
||||
if (has_phys_dev_features_2) {
|
||||
device_create_info.pNext = &local_features2;
|
||||
}
|
||||
if(info.pNext_chain.size() > 0) {
|
||||
match.back().structure->pNext = info.pNext_chain.front();
|
||||
}
|
||||
} else {
|
||||
device_create_info.pEnabledFeatures = &physical_device.features;
|
||||
}
|
||||
#else
|
||||
device_create_info.pEnabledFeatures = &physical_device.features;
|
||||
#endif
|
||||
|
||||
Device device;
|
||||
|
||||
VkResult res = detail::vulkan_functions().fp_vkCreateDevice(
|
||||
physical_device.physical_device, &device_create_info, info.allocation_callbacks, &device.device);
|
||||
if (res != VK_SUCCESS) {
|
||||
return { DeviceError::failed_create_device, res };
|
||||
}
|
||||
|
||||
device.physical_device = physical_device;
|
||||
device.surface = physical_device.surface;
|
||||
device.queue_families = physical_device.queue_families;
|
||||
|
@ -115,86 +115,6 @@ template <typename T> class Result {
|
||||
bool m_init;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
enum class InstanceError {
|
||||
vulkan_unavailable,
|
||||
vulkan_version_unavailable,
|
||||
vulkan_version_1_1_unavailable,
|
||||
vulkan_version_1_2_unavailable,
|
||||
failed_create_instance,
|
||||
failed_create_debug_messenger,
|
||||
requested_layers_not_present,
|
||||
requested_extensions_not_present,
|
||||
windowing_extensions_not_present,
|
||||
};
|
||||
enum class PhysicalDeviceError {
|
||||
no_surface_provided,
|
||||
failed_enumerate_physical_devices,
|
||||
no_physical_devices_found,
|
||||
no_suitable_device,
|
||||
};
|
||||
enum class QueueError {
|
||||
present_unavailable,
|
||||
graphics_unavailable,
|
||||
compute_unavailable,
|
||||
transfer_unavailable,
|
||||
queue_index_out_of_range,
|
||||
invalid_queue_family_index
|
||||
};
|
||||
enum class DeviceError {
|
||||
failed_create_device,
|
||||
};
|
||||
enum class SwapchainError {
|
||||
surface_handle_not_provided,
|
||||
failed_query_surface_support_details,
|
||||
failed_create_swapchain,
|
||||
failed_get_swapchain_images,
|
||||
failed_create_swapchain_image_views,
|
||||
};
|
||||
|
||||
std::error_code make_error_code(InstanceError instance_error);
|
||||
std::error_code make_error_code(PhysicalDeviceError physical_device_error);
|
||||
std::error_code make_error_code(QueueError queue_error);
|
||||
std::error_code make_error_code(DeviceError device_error);
|
||||
std::error_code make_error_code(SwapchainError swapchain_error);
|
||||
|
||||
const char* to_string_message_severity(VkDebugUtilsMessageSeverityFlagBitsEXT s);
|
||||
const char* to_string_message_type(VkDebugUtilsMessageTypeFlagsEXT s);
|
||||
|
||||
const char* to_string(InstanceError err);
|
||||
const char* to_string(PhysicalDeviceError err);
|
||||
const char* to_string(QueueError err);
|
||||
const char* to_string(DeviceError err);
|
||||
const char* to_string(SwapchainError err);
|
||||
|
||||
// Gathers useful information about the available vulkan capabilities, like layers and instance
|
||||
// extensions. Use this for enabling features conditionally, ie if you would like an extension but
|
||||
// can use a fallback if it isn't supported but need to know if support is available first.
|
||||
struct SystemInfo {
|
||||
private:
|
||||
SystemInfo();
|
||||
|
||||
public:
|
||||
// Use get_system_info to create a SystemInfo struct. This is because loading vulkan could fail.
|
||||
static detail::Result<SystemInfo> get_system_info();
|
||||
static detail::Result<SystemInfo> get_system_info(PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr);
|
||||
|
||||
// Returns true if a layer is available
|
||||
bool is_layer_available(const char* layer_name) const;
|
||||
// Returns true if an extension is available
|
||||
bool is_extension_available(const char* extension_name) const;
|
||||
|
||||
std::vector<VkLayerProperties> available_layers;
|
||||
std::vector<VkExtensionProperties> available_extensions;
|
||||
bool validation_layers_available = false;
|
||||
bool debug_utils_available = false;
|
||||
};
|
||||
|
||||
|
||||
class InstanceBuilder;
|
||||
class PhysicalDeviceSelector;
|
||||
|
||||
struct ExtensionFeatures {
|
||||
|
||||
using DeleteProc = void(*)(ExtensionFeatures&);
|
||||
@ -313,6 +233,86 @@ struct ExtensionFeatures {
|
||||
CopyProc copy_proc = nullptr;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
enum class InstanceError {
|
||||
vulkan_unavailable,
|
||||
vulkan_version_unavailable,
|
||||
vulkan_version_1_1_unavailable,
|
||||
vulkan_version_1_2_unavailable,
|
||||
failed_create_instance,
|
||||
failed_create_debug_messenger,
|
||||
requested_layers_not_present,
|
||||
requested_extensions_not_present,
|
||||
windowing_extensions_not_present,
|
||||
};
|
||||
enum class PhysicalDeviceError {
|
||||
no_surface_provided,
|
||||
failed_enumerate_physical_devices,
|
||||
no_physical_devices_found,
|
||||
no_suitable_device,
|
||||
};
|
||||
enum class QueueError {
|
||||
present_unavailable,
|
||||
graphics_unavailable,
|
||||
compute_unavailable,
|
||||
transfer_unavailable,
|
||||
queue_index_out_of_range,
|
||||
invalid_queue_family_index
|
||||
};
|
||||
enum class DeviceError {
|
||||
failed_create_device,
|
||||
};
|
||||
enum class SwapchainError {
|
||||
surface_handle_not_provided,
|
||||
failed_query_surface_support_details,
|
||||
failed_create_swapchain,
|
||||
failed_get_swapchain_images,
|
||||
failed_create_swapchain_image_views,
|
||||
};
|
||||
|
||||
std::error_code make_error_code(InstanceError instance_error);
|
||||
std::error_code make_error_code(PhysicalDeviceError physical_device_error);
|
||||
std::error_code make_error_code(QueueError queue_error);
|
||||
std::error_code make_error_code(DeviceError device_error);
|
||||
std::error_code make_error_code(SwapchainError swapchain_error);
|
||||
|
||||
const char* to_string_message_severity(VkDebugUtilsMessageSeverityFlagBitsEXT s);
|
||||
const char* to_string_message_type(VkDebugUtilsMessageTypeFlagsEXT s);
|
||||
|
||||
const char* to_string(InstanceError err);
|
||||
const char* to_string(PhysicalDeviceError err);
|
||||
const char* to_string(QueueError err);
|
||||
const char* to_string(DeviceError err);
|
||||
const char* to_string(SwapchainError err);
|
||||
|
||||
// Gathers useful information about the available vulkan capabilities, like layers and instance
|
||||
// extensions. Use this for enabling features conditionally, ie if you would like an extension but
|
||||
// can use a fallback if it isn't supported but need to know if support is available first.
|
||||
struct SystemInfo {
|
||||
private:
|
||||
SystemInfo();
|
||||
|
||||
public:
|
||||
// Use get_system_info to create a SystemInfo struct. This is because loading vulkan could fail.
|
||||
static detail::Result<SystemInfo> get_system_info();
|
||||
static detail::Result<SystemInfo> get_system_info(PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr);
|
||||
|
||||
// Returns true if a layer is available
|
||||
bool is_layer_available(const char* layer_name) const;
|
||||
// Returns true if an extension is available
|
||||
bool is_extension_available(const char* extension_name) const;
|
||||
|
||||
std::vector<VkLayerProperties> available_layers;
|
||||
std::vector<VkExtensionProperties> available_extensions;
|
||||
bool validation_layers_available = false;
|
||||
bool debug_utils_available = false;
|
||||
};
|
||||
|
||||
|
||||
class InstanceBuilder;
|
||||
class PhysicalDeviceSelector;
|
||||
|
||||
struct Instance {
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
VkDebugUtilsMessengerEXT debug_messenger = VK_NULL_HANDLE;
|
||||
@ -473,7 +473,7 @@ struct PhysicalDevice {
|
||||
uint32_t instance_version = VK_MAKE_VERSION(1, 0, 0);
|
||||
std::vector<const char*> extensions_to_enable;
|
||||
std::vector<VkQueueFamilyProperties> queue_families;
|
||||
mutable std::vector<ExtensionFeatures> extension_features;
|
||||
std::vector<detail::ExtensionFeatures> extension_features;
|
||||
bool defer_surface_initialization = false;
|
||||
friend class PhysicalDeviceSelector;
|
||||
friend class DeviceBuilder;
|
||||
@ -534,16 +534,15 @@ class PhysicalDeviceSelector {
|
||||
// Require a physical device that supports a (major, minor) version of vulkan.
|
||||
PhysicalDeviceSelector& set_minimum_version(uint32_t major, uint32_t minor);
|
||||
|
||||
// Require a physical device which supports a specific set of general/extension features.
|
||||
template <typename T>
|
||||
PhysicalDeviceSelector& add_required_features(T const& features) {
|
||||
// Require a physical device which supports a specific set of general/extension features.
|
||||
#if defined(VK_API_VERSION_1_1)
|
||||
criteria.extension_features.push_back(ExtensionFeatures::make(features));
|
||||
#endif
|
||||
template <typename T>
|
||||
PhysicalDeviceSelector& add_required_extension_features(T const& features) {
|
||||
criteria.extension_features.push_back(detail::ExtensionFeatures::make(features));
|
||||
return *this;
|
||||
}
|
||||
template<>
|
||||
PhysicalDeviceSelector& add_required_features<VkPhysicalDeviceFeatures>(VkPhysicalDeviceFeatures const& features) {
|
||||
#endif
|
||||
PhysicalDeviceSelector& set_required_features(VkPhysicalDeviceFeatures const& features) {
|
||||
criteria.required_features = features;
|
||||
return *this;
|
||||
}
|
||||
@ -581,7 +580,7 @@ class PhysicalDeviceSelector {
|
||||
VkPhysicalDeviceMemoryProperties mem_properties{};
|
||||
#if defined(VK_API_VERSION_1_1)
|
||||
VkPhysicalDeviceFeatures2 device_features2{};
|
||||
std::vector<ExtensionFeatures> extension_features;
|
||||
std::vector<detail::ExtensionFeatures> extension_features;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -590,7 +589,7 @@ class PhysicalDeviceSelector {
|
||||
|
||||
PhysicalDeviceDesc populate_device_details(uint32_t instance_version,
|
||||
VkPhysicalDevice phys_device,
|
||||
std::vector<ExtensionFeatures> extension_features_as_template) const;
|
||||
std::vector<detail::ExtensionFeatures> extension_features_as_template) const;
|
||||
|
||||
struct SelectionCriteria {
|
||||
PreferredDeviceType preferred_type = PreferredDeviceType::discrete;
|
||||
@ -612,7 +611,7 @@ class PhysicalDeviceSelector {
|
||||
VkPhysicalDeviceFeatures required_features{};
|
||||
#if defined(VK_API_VERSION_1_1)
|
||||
VkPhysicalDeviceFeatures2 required_features2{};
|
||||
std::vector<ExtensionFeatures> extension_features;
|
||||
std::vector<detail::ExtensionFeatures> extension_features;
|
||||
#endif
|
||||
bool defer_surface_initialization = false;
|
||||
bool use_first_gpu_unconditionally = false;
|
||||
@ -670,6 +669,13 @@ class DeviceBuilder {
|
||||
// If a custom queue setup is provided, getting the queues and queue indexes is up to the application.
|
||||
DeviceBuilder& custom_queue_setup(std::vector<CustomQueueDescription> queue_descriptions);
|
||||
|
||||
// Add a structure to the pNext chain of VkDeviceCreateInfo.
|
||||
// The structure must be valid when DeviceBuilder::build() is called.
|
||||
template <typename T> DeviceBuilder& add_pNext(T* structure) {
|
||||
info.pNext_chain.push_back(reinterpret_cast<VkBaseOutStructure*>(structure));
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Provide custom allocation callbacks.
|
||||
DeviceBuilder& set_allocation_callbacks(VkAllocationCallbacks* callbacks);
|
||||
|
||||
@ -677,6 +683,7 @@ class DeviceBuilder {
|
||||
PhysicalDevice physical_device;
|
||||
struct DeviceInfo {
|
||||
VkDeviceCreateFlags flags = 0;
|
||||
std::vector<VkBaseOutStructure*> pNext_chain;
|
||||
std::vector<CustomQueueDescription> queue_descriptions;
|
||||
VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE;
|
||||
} info;
|
||||
|
@ -411,6 +411,38 @@ TEST_CASE("ReLoading Vulkan Manually", "[VkBootstrap.loading]") {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(VK_API_VERSION_1_1)
|
||||
TEST_CASE("Querying Required Extension Features", "[VkBootstrap.version]") {
|
||||
GIVEN("A working instance") {
|
||||
vkb::InstanceBuilder builder;
|
||||
|
||||
auto instance_ret =
|
||||
builder.request_validation_layers().require_api_version(1, 2).set_headless().build();
|
||||
REQUIRE(instance_ret.has_value());
|
||||
// Requires a device that supports runtime descriptor arrays via descriptor indexing extension.
|
||||
{
|
||||
VkPhysicalDeviceDescriptorIndexingFeaturesEXT descriptor_indexing_features{};
|
||||
descriptor_indexing_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT;
|
||||
descriptor_indexing_features.runtimeDescriptorArray = true;
|
||||
|
||||
vkb::PhysicalDeviceSelector selector(instance_ret.value());
|
||||
auto phys_dev_ret =
|
||||
selector.add_required_extension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME).
|
||||
add_required_extension_features(descriptor_indexing_features).select();
|
||||
// Ignore if hardware support isn't true
|
||||
REQUIRE(phys_dev_ret.has_value());
|
||||
|
||||
vkb::DeviceBuilder device_builder(phys_dev_ret.value());
|
||||
auto device_ret = device_builder.build();
|
||||
REQUIRE(device_ret.has_value());
|
||||
vkb::destroy_device(device_ret.value());
|
||||
}
|
||||
vkb::destroy_instance(instance_ret.value());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(VK_API_VERSION_1_2)
|
||||
TEST_CASE("Querying Vulkan 1.1 and 1.2 features", "[VkBootstrap.version]") {
|
||||
GIVEN("A working instance") {
|
||||
|
Loading…
Reference in New Issue
Block a user