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

@ -16,26 +16,26 @@ option(VK_BOOTSTRAP_TEST "Test Vk-Bootstrap with glfw and Catch2" OFF)
if (VK_BOOTSTRAP_TEST)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_INSTALL OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
add_subdirectory(ext/glfw)
add_subdirectory(ext/Catch2)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_INSTALL OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
add_subdirectory(ext/glfw)
add_subdirectory(ext/Catch2)
add_executable(vk-bootstrap-test tests/run_tests.cpp)
add_executable(vk-bootstrap-test tests/run_tests.cpp)
target_link_libraries(vk-bootstrap-test vk-bootstrap)
target_link_libraries(vk-bootstrap-test glfw)
target_link_libraries(vk-bootstrap-test Catch2)
target_link_libraries(vk-bootstrap-test vk-bootstrap)
target_link_libraries(vk-bootstrap-test glfw)
target_link_libraries(vk-bootstrap-test Catch2)
add_executable(vk-bootstrap-triangle example/triangle.cpp)
target_link_libraries(vk-bootstrap-triangle vk-bootstrap)
target_link_libraries(vk-bootstrap-triangle glfw)
add_executable(vk-bootstrap-triangle example/triangle.cpp)
target_link_libraries(vk-bootstrap-triangle vk-bootstrap)
target_link_libraries(vk-bootstrap-triangle glfw)
add_custom_command(
TARGET vk-bootstrap-triangle POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/example/shaders ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}
)
add_custom_command(
TARGET vk-bootstrap-triangle POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/example/shaders ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}
)
endif()

View File

@ -42,8 +42,7 @@ int device_initialization (Init& init) {
init.window = create_window_glfw (false);
vkb::InstanceBuilder instance_builder;
auto instance_ret =
instance_builder.set_default_debug_messenger ().check_and_setup_validation_layers ().build ();
auto instance_ret = instance_builder.use_default_debug_messenger ().request_validation_layers ().build ();
if (!instance_ret) {
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
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) {
if (instance.instance != VK_NULL_HANDLE) {
if (instance.debug_messenger != nullptr)
@ -165,17 +190,8 @@ void destroy_instance (Instance instance) {
vkDestroyInstance (instance.instance, nullptr);
}
}
InstanceBuilder::InstanceBuilder () {
auto available_extensions =
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 ();
}
}
SystemInfo InstanceBuilder::get_system_info () { return system; }
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);
return *this;
}
InstanceBuilder& InstanceBuilder::must_enable_extension (const char* extension_name) {
if (!extension_name) return *this;
info.extensions.push_back (extension_name);
return *this;
}
InstanceBuilder& InstanceBuilder::check_and_add_layer (const char* layer_name) {
InstanceBuilder& InstanceBuilder::request_layer (const char* layer_name) {
if (!layer_name) return *this;
if (detail::check_layer_supported (system.available_layers, layer_name))
info.layers.push_back (layer_name);
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 (detail::check_extension_supported (system.available_extensions, 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;
return *this;
}
InstanceBuilder& InstanceBuilder::check_and_setup_validation_layers (bool enable_validation) {
bool available =
InstanceBuilder& InstanceBuilder::request_validation_layers (bool enable_validation) {
info.enable_validation_layers =
enable_validation &&
detail::check_extension_supported (system.available_extensions, detail::validation_layer_name);
info.enable_validation_layers = available;
return *this;
}
InstanceBuilder& InstanceBuilder::set_default_debug_messenger () {
InstanceBuilder& InstanceBuilder::use_default_debug_messenger () {
info.use_debug_messenger = true;
info.debug_callback = default_debug_callback;
return *this;

View File

@ -97,6 +97,20 @@ template <typename E, typename U> class Expected {
/* TODO implement operator == and operator != as friend or global */
} // 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 {
failed_create_instance,
failed_create_debug_messenger,
@ -124,8 +138,10 @@ void destroy_instance (Instance instance); // release instance resources
class InstanceBuilder {
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 ();
// 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.
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.
InstanceBuilder& must_enable_layer (const char* layer_name);
// 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.
InstanceBuilder& must_enable_extension (const char* extension_name);
// Headless Mode does not load the required extensions for presentation. Defaults to 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.
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.
InstanceBuilder& set_default_debug_messenger ();
InstanceBuilder& use_default_debug_messenger ();
// Provide a user defined debug callback.
InstanceBuilder& set_debug_callback (PFN_vkDebugUtilsMessengerCallbackEXT callback);
// Set what message severity is needed to trigger the callback.
@ -216,10 +234,7 @@ class InstanceBuilder {
bool headless_context = false;
} info;
struct SystemInfo {
std::vector<VkLayerProperties> available_layers;
std::vector<VkExtensionProperties> available_extensions;
} system;
SystemInfo system;
};
const char* to_string_message_severity (VkDebugUtilsMessageSeverityFlagBitsEXT s);

View File

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