Renamed many InstanceBuilder functions, added SystemInfo struct.

SystemInfo will be the way for users to know what is and isn't available on their system.
Currently, it only has booleans for if validation layers and debug messenger are available,
but more could be added in the future.
This commit is contained in:
Charles Giessen 2020-03-07 01:44:34 -07:00
parent 6933882f63
commit a4ab8e099d
5 changed files with 89 additions and 59 deletions

View File

@ -42,8 +42,7 @@ int device_initialization (Init& init) {
init.window = create_window_glfw (false); init.window = create_window_glfw (false);
vkb::InstanceBuilder instance_builder; vkb::InstanceBuilder instance_builder;
auto instance_ret = auto instance_ret = instance_builder.use_default_debug_messenger ().request_validation_layers ().build ();
instance_builder.set_default_debug_messenger ().check_and_setup_validation_layers ().build ();
if (!instance_ret) { if (!instance_ret) {
std::cout << static_cast<uint32_t> (instance_ret.error ().type) << "\n"; std::cout << static_cast<uint32_t> (instance_ret.error ().type) << "\n";
} }

View File

@ -158,6 +158,31 @@ const char* validation_layer_name = "VK_LAYER_KHRONOS_validation";
} // namespace detail } // namespace detail
SystemInfo::SystemInfo () {
auto available_extensions =
detail::get_vector<VkExtensionProperties> (vkEnumerateInstanceExtensionProperties, nullptr);
if (available_extensions.has_value ()) {
this->available_extensions = available_extensions.value ();
}
for (auto& ext : this->available_extensions)
if (ext.extensionName == VK_EXT_DEBUG_UTILS_EXTENSION_NAME)
debug_messenger_available = true;
auto available_layers = detail::get_vector<VkLayerProperties> (vkEnumerateInstanceLayerProperties);
if (available_layers.has_value ()) {
available_layers = available_layers.value ();
}
for (auto& layer : this->available_layers)
if (layer.layerName == detail::validation_layer_name) validation_layers_available = true;
}
bool SystemInfo::is_extension_available (const char* extension_name) {
if (!extension_name) return false;
return detail::check_extension_supported (available_extensions, extension_name);
}
bool SystemInfo::is_layer_available (const char* layer_name) {
if (!layer_name) return false;
return detail::check_layer_supported (available_layers, layer_name);
}
void destroy_instance (Instance instance) { void destroy_instance (Instance instance) {
if (instance.instance != VK_NULL_HANDLE) { if (instance.instance != VK_NULL_HANDLE) {
if (instance.debug_messenger != nullptr) if (instance.debug_messenger != nullptr)
@ -165,17 +190,8 @@ void destroy_instance (Instance instance) {
vkDestroyInstance (instance.instance, nullptr); vkDestroyInstance (instance.instance, nullptr);
} }
} }
InstanceBuilder::InstanceBuilder () {
auto available_extensions = SystemInfo InstanceBuilder::get_system_info () { return system; }
detail::get_vector<VkExtensionProperties> (vkEnumerateInstanceExtensionProperties, nullptr);
if (available_extensions.has_value ()) {
system.available_extensions = available_extensions.value ();
}
auto available_layers = detail::get_vector<VkLayerProperties> (vkEnumerateInstanceLayerProperties);
if (available_layers.has_value ()) {
system.available_layers = available_layers.value ();
}
}
detail::Expected<Instance, detail::Error<InstanceError>> InstanceBuilder::build () { detail::Expected<Instance, detail::Error<InstanceError>> InstanceBuilder::build () {
@ -317,18 +333,18 @@ InstanceBuilder& InstanceBuilder::must_enable_layer (const char* layer_name) {
info.layers.push_back (layer_name); info.layers.push_back (layer_name);
return *this; return *this;
} }
InstanceBuilder& InstanceBuilder::must_enable_extension (const char* extension_name) { InstanceBuilder& InstanceBuilder::request_layer (const char* layer_name) {
if (!extension_name) return *this;
info.extensions.push_back (extension_name);
return *this;
}
InstanceBuilder& InstanceBuilder::check_and_add_layer (const char* layer_name) {
if (!layer_name) return *this; if (!layer_name) return *this;
if (detail::check_layer_supported (system.available_layers, layer_name)) if (detail::check_layer_supported (system.available_layers, layer_name))
info.layers.push_back (layer_name); info.layers.push_back (layer_name);
return *this; return *this;
} }
InstanceBuilder& InstanceBuilder::check_and_add_extension (const char* extension_name) { InstanceBuilder& InstanceBuilder::must_enable_extension (const char* extension_name) {
if (!extension_name) return *this;
info.extensions.push_back (extension_name);
return *this;
}
InstanceBuilder& InstanceBuilder::request_extension (const char* extension_name) {
if (!extension_name) return *this; if (!extension_name) return *this;
if (detail::check_extension_supported (system.available_extensions, extension_name)) if (detail::check_extension_supported (system.available_extensions, extension_name))
info.extensions.push_back (extension_name); info.extensions.push_back (extension_name);
@ -338,14 +354,14 @@ InstanceBuilder& InstanceBuilder::must_enable_validation_layers (bool enable_val
info.enable_validation_layers = enable_validation; info.enable_validation_layers = enable_validation;
return *this; return *this;
} }
InstanceBuilder& InstanceBuilder::check_and_setup_validation_layers (bool enable_validation) { InstanceBuilder& InstanceBuilder::request_validation_layers (bool enable_validation) {
bool available = info.enable_validation_layers =
enable_validation &&
detail::check_extension_supported (system.available_extensions, detail::validation_layer_name); detail::check_extension_supported (system.available_extensions, detail::validation_layer_name);
info.enable_validation_layers = available;
return *this; return *this;
} }
InstanceBuilder& InstanceBuilder::set_default_debug_messenger () { InstanceBuilder& InstanceBuilder::use_default_debug_messenger () {
info.use_debug_messenger = true; info.use_debug_messenger = true;
info.debug_callback = default_debug_callback; info.debug_callback = default_debug_callback;
return *this; return *this;

View File

@ -97,6 +97,20 @@ template <typename E, typename U> class Expected {
/* TODO implement operator == and operator != as friend or global */ /* TODO implement operator == and operator != as friend or global */
} // namespace detail } // namespace detail
struct SystemInfo {
SystemInfo ();
// Returns true if a layer is available
bool is_layer_available (const char* layer_name);
// Returns true if an extension is available
bool is_extension_available (const char* extension_name);
std::vector<VkLayerProperties> available_layers;
std::vector<VkExtensionProperties> available_extensions;
bool validation_layers_available = false;
bool debug_messenger_available = false;
};
enum class InstanceError { enum class InstanceError {
failed_create_instance, failed_create_instance,
failed_create_debug_messenger, failed_create_debug_messenger,
@ -124,8 +138,10 @@ void destroy_instance (Instance instance); // release instance resources
class InstanceBuilder { class InstanceBuilder {
public: public:
InstanceBuilder (); // automatically gets available layers and extensions. // contains useful information about the available vulkan capabilities, like layers and instance extensions.
SystemInfo get_system_info ();
// Create a VkInstance. Return an error if it failed.
detail::Expected<Instance, detail::Error<InstanceError>> build (); detail::Expected<Instance, detail::Error<InstanceError>> build ();
// Sets the name of the application. Defaults to "" if none is provided. // Sets the name of the application. Defaults to "" if none is provided.
@ -141,23 +157,25 @@ class InstanceBuilder {
// Loads the specified layer if it is available. // Loads the specified layer if it is available.
InstanceBuilder& check_and_add_layer (const char* layer_name); InstanceBuilder& request_layer (const char* layer_name);
// Adds a layer to be enabled. Will fail to create an instance if the layer isn't available. // Adds a layer to be enabled. Will fail to create an instance if the layer isn't available.
InstanceBuilder& must_enable_layer (const char* layer_name); InstanceBuilder& must_enable_layer (const char* layer_name);
// Enables the specified extension if it is available. // Enables the specified extension if it is available.
InstanceBuilder& check_and_add_extension (const char* extension_name); InstanceBuilder& request_extension (const char* extension_name);
// Adds an extension to be enabled. Will fail to create an instance if the extension isn't available. // Adds an extension to be enabled. Will fail to create an instance if the extension isn't available.
InstanceBuilder& must_enable_extension (const char* extension_name); InstanceBuilder& must_enable_extension (const char* extension_name);
// Headless Mode does not load the required extensions for presentation. Defaults to false. // Headless Mode does not load the required extensions for presentation. Defaults to false.
InstanceBuilder& set_headless (bool headless = false); InstanceBuilder& set_headless (bool headless = false);
// Checks if the validation layers are available and loads them if they are.
InstanceBuilder& check_and_setup_validation_layers (bool enable_validation = true);
// Enables the validation layers. Will fail to create an instance if the validation layers aren't available. // Enables the validation layers. Will fail to create an instance if the validation layers aren't available.
InstanceBuilder& must_enable_validation_layers (bool enable_validation = true); InstanceBuilder& must_enable_validation_layers (bool require_validation = true);
// Checks if the validation layers are available and loads them if they are.
InstanceBuilder& request_validation_layers (bool enable_validation = true);
// Use a default debug callback that prints to standard out. // Use a default debug callback that prints to standard out.
InstanceBuilder& set_default_debug_messenger (); InstanceBuilder& use_default_debug_messenger ();
// Provide a user defined debug callback. // Provide a user defined debug callback.
InstanceBuilder& set_debug_callback (PFN_vkDebugUtilsMessengerCallbackEXT callback); InstanceBuilder& set_debug_callback (PFN_vkDebugUtilsMessengerCallbackEXT callback);
// Set what message severity is needed to trigger the callback. // Set what message severity is needed to trigger the callback.
@ -216,10 +234,7 @@ class InstanceBuilder {
bool headless_context = false; bool headless_context = false;
} info; } info;
struct SystemInfo { SystemInfo system;
std::vector<VkLayerProperties> available_layers;
std::vector<VkExtensionProperties> available_extensions;
} system;
}; };
const char* to_string_message_severity (VkDebugUtilsMessageSeverityFlagBitsEXT s); const char* to_string_message_severity (VkDebugUtilsMessageSeverityFlagBitsEXT s);

View File

@ -6,7 +6,7 @@ int test_happy_path () {
auto window = create_window_glfw (); auto window = create_window_glfw ();
vkb::InstanceBuilder instance_builder; vkb::InstanceBuilder instance_builder;
auto instance_ret = instance_builder.set_default_debug_messenger ().build (); auto instance_ret = instance_builder.use_default_debug_messenger ().build ();
if (!instance_ret) { if (!instance_ret) {
std::cout << static_cast<uint32_t> (instance_ret.error ().type) << "\n"; std::cout << static_cast<uint32_t> (instance_ret.error ().type) << "\n";
return -1; // couldn't make instance return -1; // couldn't make instance
@ -44,7 +44,7 @@ int test_instance_basic () {
vkb::InstanceBuilder builder; vkb::InstanceBuilder builder;
auto instance_ret = auto instance_ret =
builder.check_and_setup_validation_layers () builder.request_validation_layers ()
.set_app_name ("test") .set_app_name ("test")
.set_debug_callback ([] (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, .set_debug_callback ([] (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType, VkDebugUtilsMessageTypeFlagsEXT messageType,
@ -71,13 +71,13 @@ int test_instance_headless () {
vkb::InstanceBuilder builder; vkb::InstanceBuilder builder;
auto instance_ret = auto instance_ret =
builder.check_and_setup_validation_layers () builder.request_validation_layers ()
.set_headless () .set_headless ()
.set_app_version (4, 5, 6) .set_app_version (4, 5, 6)
.set_app_name ("headless") .set_app_name ("headless")
.set_engine_name ("nick") .set_engine_name ("nick")
.set_api_version (1, 0, 34) .set_api_version (1, 0, 34)
.set_default_debug_messenger () .use_default_debug_messenger ()
.add_validation_feature_enable (VkValidationFeatureEnableEXT::VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT) .add_validation_feature_enable (VkValidationFeatureEnableEXT::VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT)
.add_validation_feature_disable (VkValidationFeatureDisableEXT::VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT) .add_validation_feature_disable (VkValidationFeatureDisableEXT::VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT)
.add_validation_disable (VkValidationCheckEXT::VK_VALIDATION_CHECK_SHADERS_EXT) .add_validation_disable (VkValidationCheckEXT::VK_VALIDATION_CHECK_SHADERS_EXT)
@ -93,7 +93,7 @@ int test_physical_device_selection () {
printf ("\nphysical device selection\n"); printf ("\nphysical device selection\n");
vkb::InstanceBuilder instance_builder; vkb::InstanceBuilder instance_builder;
auto instance_ret = instance_builder.set_default_debug_messenger ().build (); auto instance_ret = instance_builder.use_default_debug_messenger ().build ();
auto instance = instance_ret.value (); auto instance = instance_ret.value ();
auto window = create_window_glfw (); auto window = create_window_glfw ();
auto surface = create_surface_glfw (instance.instance, window); auto surface = create_surface_glfw (instance.instance, window);
@ -117,7 +117,7 @@ int test_physical_device_selection () {
int test_device_creation () { int test_device_creation () {
printf ("\ndevice creation\n"); printf ("\ndevice creation\n");
vkb::InstanceBuilder instance_builder; vkb::InstanceBuilder instance_builder;
auto instance_ret = instance_builder.set_default_debug_messenger ().build (); auto instance_ret = instance_builder.use_default_debug_messenger ().build ();
if (!instance_ret.has_value ()) { if (!instance_ret.has_value ()) {
printf ("couldn't create instance %i\n", static_cast<uint32_t> (instance_ret.error ().type)); printf ("couldn't create instance %i\n", static_cast<uint32_t> (instance_ret.error ().type));
return -1; return -1;