Implemented missing instance functions, deleted surface in tests.

This commit is contained in:
Charles Giessen 2020-02-18 15:18:08 -07:00
parent b171ced11e
commit 7de79b81b1
4 changed files with 110 additions and 62 deletions

View File

@ -106,44 +106,42 @@ VkBool32 default_debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageS
}
namespace detail {
bool check_layers_supported (std::vector<const char*> layer_names) {
auto available_layers = detail::get_vector<VkLayerProperties> (vkEnumerateInstanceLayerProperties);
if (!available_layers.has_value ()) {
return false; // maybe report error?
bool check_layer_supported (std::vector<VkLayerProperties> available_layers, const char* layer_name) {
if (!layer_name) return false;
for (const auto& layer_properties : available_layers) {
if (strcmp (layer_name, layer_properties.layerName) == 0) {
return true;
}
}
return false;
}
bool check_layers_supported (std::vector<VkLayerProperties> available_layers, std::vector<const char*> layer_names) {
bool all_found = true;
for (const auto& layer_name : layer_names) {
bool found = false;
for (const auto& layer_properties : available_layers.value ()) {
if (strcmp (layer_name, layer_properties.layerName) == 0) {
found = true;
break;
}
}
bool found = check_layer_supported (available_layers, layer_name);
if (!found) all_found = false;
}
return all_found;
}
bool check_extensions_supported (std::vector<const char*> extension_names) {
auto available_extensions =
detail::get_vector<VkExtensionProperties> (vkEnumerateInstanceExtensionProperties, nullptr);
if (!available_extensions.has_value ()) {
return false; // maybe report error?
bool check_extension_supported (std::vector<VkExtensionProperties> available_extensions, const char* extension_name) {
if (!extension_name) return false;
for (const auto& layer_properties : available_extensions) {
if (strcmp (extension_name, layer_properties.extensionName) == 0) {
return true;
}
}
return false;
}
bool check_extensions_supported (std::vector<VkExtensionProperties> available_extensions,
std::vector<const char*> extension_names) {
bool all_found = true;
for (const auto& extension_name : extension_names) {
bool found = false;
for (const auto& layer_properties : available_extensions.value ()) {
if (strcmp (extension_name, layer_properties.extensionName) == 0) {
found = true;
break;
}
}
bool found = check_extension_supported (available_extensions, extension_name);
if (!found) all_found = false;
}
return all_found;
}
@ -156,6 +154,8 @@ void setup_pNext_chain (T& structure, std::vector<VkBaseOutStructure*> const& st
}
structure.pNext = structs.at (0);
}
const char* validation_layer_name = "VK_LAYER_KHRONOS_validation";
} // namespace detail
void destroy_instance (Instance instance) {
@ -165,6 +165,17 @@ 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 ();
}
}
detail::Expected<Instance, detail::Error<InstanceError>> InstanceBuilder::build () {
@ -200,7 +211,7 @@ detail::Expected<Instance, detail::Error<InstanceError>> InstanceBuilder::build
extensions.push_back ("VK_KHR_metal_surface");
#endif
}
bool all_extensions_supported = detail::check_extensions_supported (extensions);
bool all_extensions_supported = detail::check_extensions_supported (system.available_extensions, extensions);
if (!all_extensions_supported) {
return detail::Error<InstanceError>{ InstanceError::requested_extensions_not_present };
}
@ -210,9 +221,9 @@ detail::Expected<Instance, detail::Error<InstanceError>> InstanceBuilder::build
layers.push_back (layer);
if (info.enable_validation_layers) {
layers.push_back ("VK_LAYER_KHRONOS_validation");
layers.push_back (detail::validation_layer_name);
}
bool all_layers_supported = detail::check_layers_supported (layers);
bool all_layers_supported = detail::check_layers_supported (system.available_layers, layers);
if (!all_layers_supported) {
return detail::Error<InstanceError>{ InstanceError::requested_layers_not_present };
}
@ -280,10 +291,12 @@ detail::Expected<Instance, detail::Error<InstanceError>> InstanceBuilder::build
}
InstanceBuilder& InstanceBuilder::set_app_name (const char* app_name) {
if (!app_name) return *this;
info.app_name = app_name;
return *this;
}
InstanceBuilder& InstanceBuilder::set_engine_name (const char* engine_name) {
if (!engine_name) return *this;
info.engine_name = engine_name;
return *this;
}
@ -300,17 +313,38 @@ InstanceBuilder& InstanceBuilder::set_api_version (uint32_t major, uint32_t mino
return *this;
}
InstanceBuilder& InstanceBuilder::add_layer (const char* layer_name) {
if (!layer_name) return *this;
info.layers.push_back (layer_name);
return *this;
}
InstanceBuilder& InstanceBuilder::add_extension (const char* extension_name) {
if (!extension_name) return *this;
info.extensions.push_back (extension_name);
return *this;
}
bool InstanceBuilder::check_and_add_layer (const char* layer_name) {
if (!layer_name) return false;
bool available = detail::check_layer_supported (system.available_layers, layer_name);
if (available) info.layers.push_back (layer_name);
return available;
}
bool InstanceBuilder::check_and_add_extension (const char* extension_name) {
if (!extension_name) return false;
bool available = detail::check_extension_supported (system.available_extensions, extension_name);
if (available) info.extensions.push_back (extension_name);
return available;
}
InstanceBuilder& InstanceBuilder::setup_validation_layers (bool enable_validation) {
info.enable_validation_layers = enable_validation;
return *this;
}
bool InstanceBuilder::check_and_setup_validation_layers (bool enable_validation) {
bool available =
detail::check_extension_supported (system.available_extensions, detail::validation_layer_name);
setup_validation_layers (available);
return available;
}
InstanceBuilder& InstanceBuilder::set_default_debug_messenger () {
info.use_debug_messenger = true;
info.debug_callback = default_debug_callback;
@ -394,25 +428,6 @@ Expected<SurfaceSupportDetails, detail::Error<SurfaceSupportError>> query_surfac
return SurfaceSupportDetails{ capabilities, formats.value (), present_modes.value () };
}
// Given a list of formats, return a format supported by the hardware, else return VK_FORMAT_UNDEFINED
VkFormat find_supported_format (VkPhysicalDevice physical_device,
const std::vector<VkFormat>& candidates,
VkImageTiling tiling,
VkFormatFeatureFlags features) {
for (VkFormat format : candidates) {
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties (physical_device, format, &props);
if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) {
return format;
} else if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) {
return format;
}
}
return VK_FORMAT_UNDEFINED;
}
std::vector<const char*> check_device_extension_support (
VkPhysicalDevice device, std::vector<const char*> desired_extensions) {
auto available_extensions =
@ -491,12 +506,15 @@ bool supports_features (VkPhysicalDeviceFeatures supported, VkPhysicalDeviceFeat
}
} // namespace detail
// finds the first queue which supports graphics operations. returns -1 if none is found
int get_graphics_queue_index (std::vector<VkQueueFamilyProperties> const& families) {
for (int i = 0; i < families.size (); i++) {
if (families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) return i;
}
return -1;
}
// finds a compute queue which is distinct from the graphics queue and tries to find one without transfer support
// returns -1 if none is found
int get_distinct_compute_queue_index (std::vector<VkQueueFamilyProperties> const& families) {
int compute = -1;
for (int i = 0; i < families.size (); i++) {
@ -511,6 +529,8 @@ int get_distinct_compute_queue_index (std::vector<VkQueueFamilyProperties> const
}
return compute;
}
// finds a transfer queue which is distinct from the graphics queue and tries to find one without compute support
// returns -1 if none is found
int get_distinct_transfer_queue_index (std::vector<VkQueueFamilyProperties> const& families) {
int transfer = -1;
for (int i = 0; i < families.size (); i++) {
@ -523,8 +543,29 @@ int get_distinct_transfer_queue_index (std::vector<VkQueueFamilyProperties> cons
}
}
}
return transfer;
}
// finds the first queue which supports only compute (not graphics or transfer). returns -1 if none is found
int get_dedicated_compute_queue_index (std::vector<VkQueueFamilyProperties> const& families) {
for (int i = 0; i < families.size (); i++) {
if ((families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) &&
(families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0 &&
(families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) == 0)
return i;
}
return -1;
}
// finds the first queue which supports only transfer (not graphics or compute). returns -1 if none is found
int get_dedicated_transfer_queue_index (std::vector<VkQueueFamilyProperties> const& families) {
for (int i = 0; i < families.size (); i++) {
if ((families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) &&
(families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0 &&
(families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0)
return i;
}
return -1;
}
// finds the first queue which supports presenting. returns -1 if none is found
int get_present_queue_index (VkPhysicalDevice const phys_device,
VkSurfaceKHR const surface,
std::vector<VkQueueFamilyProperties> const& families) {

View File

@ -124,6 +124,8 @@ void destroy_instance (Instance instance); // release instance resources
class InstanceBuilder {
public:
InstanceBuilder(); //automatically gets available layers and extensions
detail::Expected<Instance, detail::Error<InstanceError>> build (); // use builder pattern
InstanceBuilder& set_app_name (const char* app_name);
@ -133,11 +135,11 @@ class InstanceBuilder {
InstanceBuilder& set_engine_version (uint32_t major, uint32_t minor, uint32_t patch);
InstanceBuilder& set_api_version (uint32_t major, uint32_t minor, uint32_t patch);
InstanceBuilder& add_layer (const char* app_name);
InstanceBuilder& add_extension (const char* app_name);
InstanceBuilder& add_layer (const char* layer_name);
InstanceBuilder& add_extension (const char* extension_name);
bool check_and_add_layer (const char* app_name);
bool check_and_add_extension (const char* app_name);
bool check_and_add_layer (const char* layer_name);
bool check_and_add_extension (const char* extension_name);
InstanceBuilder& setup_validation_layers (bool enable_validation = true);
InstanceBuilder& set_headless (bool headless = false);
@ -189,6 +191,11 @@ class InstanceBuilder {
bool use_debug_messenger = false;
bool headless_context = false;
} info;
struct SystemInfo {
std::vector<VkLayerProperties> available_layers;
std::vector<VkExtensionProperties> available_extensions;
} system;
};
const char* to_string_message_severity (VkDebugUtilsMessageSeverityFlagBitsEXT s);

View File

@ -10,29 +10,24 @@
#include "../src/VkBootstrap.h"
GLFWwindow* create_window_glfw (bool resize = true)
{
GLFWwindow* create_window_glfw (bool resize = true) {
glfwInit ();
glfwWindowHint (GLFW_CLIENT_API, GLFW_NO_API);
if (!resize) glfwWindowHint (GLFW_RESIZABLE, GLFW_FALSE);
return glfwCreateWindow (640, 480, "Vulkan Triangle", NULL, NULL);
}
void destroy_window_glfw (GLFWwindow* window)
{
void destroy_window_glfw (GLFWwindow* window) {
glfwDestroyWindow (window);
glfwTerminate ();
}
VkSurfaceKHR create_surface_glfw (VkInstance instance, GLFWwindow* window)
{
VkSurfaceKHR create_surface_glfw (VkInstance instance, GLFWwindow* window) {
VkSurfaceKHR surface = nullptr;
VkResult err = glfwCreateWindowSurface (instance, window, NULL, &surface);
if (err)
{
if (err) {
const char* error_msg;
int ret = glfwGetError (&error_msg);
if (ret != 0)
{
if (ret != 0) {
std::cout << ret << " ";
if (error_msg != nullptr) std::cout << error_msg;
std::cout << "\n";
@ -40,4 +35,7 @@ VkSurfaceKHR create_surface_glfw (VkInstance instance, GLFWwindow* window)
surface = nullptr;
}
return surface;
}
void destroy_surface (VkInstance instance, VkSurfaceKHR surface) {
vkDestroySurfaceKHR (instance, surface, nullptr);
}

View File

@ -31,6 +31,7 @@ int test_happy_path () {
// possible swapchain creation...
vkb::destroy_device (device);
destroy_surface (instance.instance, surface);
vkb::destroy_instance (instance);
destroy_window_glfw (window);
return 0;
@ -107,6 +108,7 @@ int test_physical_device_selection () {
if (!phys_dev_ret.has_value ()) {
return -1;
}
destroy_surface (instance.instance, surface);
vkb::destroy_instance (instance);
destroy_window_glfw (window);
return 0;
@ -139,8 +141,8 @@ int test_device_creation () {
printf ("couldn't create device %i\n", static_cast<uint32_t> (dev_ret.error ().type));
return -1;
}
vkb::destroy_device (dev_ret.value ());
destroy_surface (instance.instance, surface);
vkb::destroy_instance (instance);
destroy_window_glfw (window);
return 0;