Moved some functions to .cpp, modified preferred physical device.

Also adjusted the .clang-format for better legibility of code
This commit is contained in:
Charles Giessen 2020-02-06 15:46:14 -07:00
parent c30782a106
commit 8b33c46bf9
2 changed files with 328 additions and 544 deletions

File diff suppressed because it is too large Load Diff

View File

@ -8,39 +8,32 @@
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
namespace vkb namespace vkb {
{
namespace detail namespace detail {
{
enum class BootstrapErrorType : uint32_t enum class BootstrapErrorType : uint32_t {
{
}; };
struct Error struct Error {
{
VkResult error_code; VkResult error_code;
const char* msg; const char* msg;
}; };
template <typename E, typename U> class Expected template <typename E, typename U> class Expected {
{
public: public:
Expected (const E& expect) : m_expect{ expect }, m_init{ true } {} Expected (const E& expect) : m_expect{ expect }, m_init{ true } {}
Expected (E&& expect) : m_expect{ std::move (expect) }, m_init{ true } {} Expected (E&& expect) : m_expect{ std::move (expect) }, m_init{ true } {}
Expected (const Error& error) : m_error{ error }, m_init{ false } {} Expected (const Error& error) : m_error{ error }, m_init{ false } {}
Expected (Error&& error) : m_error{ std::move (error) }, m_init{ false } {} Expected (Error&& error) : m_error{ std::move (error) }, m_init{ false } {}
~Expected () { destroy (); } ~Expected () { destroy (); }
Expected (Expected const& expected) : m_init (expected.m_init) Expected (Expected const& expected) : m_init (expected.m_init) {
{
if (m_init) if (m_init)
new (&m_expect) E{ expected.m_expect }; new (&m_expect) E{ expected.m_expect };
else else
new (&m_error) Error{ expected.m_error }; new (&m_error) Error{ expected.m_error };
} }
Expected (Expected&& expected) : m_init (expected.m_init) Expected (Expected&& expected) : m_init (expected.m_init) {
{
if (m_init) if (m_init)
new (&m_expect) E{ std::move (expected.m_expect) }; new (&m_expect) E{ std::move (expected.m_expect) };
else else
@ -48,29 +41,25 @@ template <typename E, typename U> class Expected
expected.destroy (); expected.destroy ();
} }
Expected& operator= (const E& expect) Expected& operator= (const E& expect) {
{
destroy (); destroy ();
m_init = true; m_init = true;
new (&m_expect) E{ expect }; new (&m_expect) E{ expect };
return *this; return *this;
} }
Expected& operator= (E&& expect) Expected& operator= (E&& expect) {
{
destroy (); destroy ();
m_init = true; m_init = true;
new (&m_expect) E{ std::move (expect) }; new (&m_expect) E{ std::move (expect) };
return *this; return *this;
} }
Expected& operator= (const Error& error) Expected& operator= (const Error& error) {
{
destroy (); destroy ();
m_init = false; m_init = false;
new (&m_error) Error{ error }; new (&m_error) Error{ error };
return *this; return *this;
} }
Expected& operator= (Error&& error) Expected& operator= (Error&& error) {
{
destroy (); destroy ();
m_init = false; m_init = false;
new (&m_error) Error{ std::move (error) }; new (&m_error) Error{ std::move (error) };
@ -95,8 +84,7 @@ template <typename E, typename U> class Expected
explicit operator bool () const { return m_init; } explicit operator bool () const { return m_init; }
private: private:
void destroy () void destroy () {
{
if (m_init) if (m_init)
m_expect.~E (); m_expect.~E ();
else else
@ -111,86 +99,27 @@ 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 */
// Helper for robustly executing the two-call pattern
template <typename T, typename F, typename... Ts>
auto get_vector_init (F&& f, T init, Ts&&... ts) -> Expected<std::vector<T>, VkResult>
{
uint32_t count = 0;
std::vector<T> results;
VkResult err;
do
{
err = f (ts..., &count, nullptr);
if (err)
{
return Error{ err, "" };
};
results.resize (count, init);
err = f (ts..., &count, results.data ());
} while (err == VK_INCOMPLETE);
if (err)
{
return Error{ err, "" };
};
return results;
}
template <typename T, typename F, typename... Ts>
auto get_vector (F&& f, Ts&&... ts) -> Expected<std::vector<T>, VkResult>
{
return get_vector_init (f, T (), ts...);
}
template <typename T, typename F, typename... Ts>
auto get_vector_noerror (F&& f, T init, Ts&&... ts) -> std::vector<T>
{
uint32_t count = 0;
std::vector<T> results;
f (ts..., &count, nullptr);
results.resize (count, init);
f (ts..., &count, results.data ());
return results;
}
template <typename T, typename F, typename... Ts>
auto get_vector_noerror (F&& f, Ts&&... ts) -> std::vector<T>
{
return get_vector_noerror (f, T (), ts...);
}
VkResult create_debug_utils_messenger (VkInstance instance,
PFN_vkDebugUtilsMessengerCallbackEXT debug_callback,
VkDebugUtilsMessageSeverityFlagsEXT severity,
VkDebugUtilsMessageTypeFlagsEXT type,
VkDebugUtilsMessengerEXT* pDebugMessenger);
void destroy_debug_utils_messenger (VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger);
static VKAPI_ATTR VkBool32 VKAPI_CALL default_debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData);
bool check_layers_supported (std::vector<const char*> layer_names);
} // namespace detail } // namespace detail
const char* to_string_message_severity (VkDebugUtilsMessageSeverityFlagBitsEXT s); class InstanceBuilder;
const char* to_string_message_type (VkDebugUtilsMessageTypeFlagsEXT s); class PhysicalDeviceSelector;
struct Instance struct Instance {
{
VkInstance instance = VK_NULL_HANDLE; VkInstance instance = VK_NULL_HANDLE;
VkDebugUtilsMessengerEXT debug_messenger = VK_NULL_HANDLE; VkDebugUtilsMessengerEXT debug_messenger = VK_NULL_HANDLE;
private:
bool headless = false; bool headless = false;
bool validation_enabled = false; bool validation_enabled = false;
bool debug_callback_enabled = false; bool debug_callback_enabled = false;
friend class InstanceBuilder;
friend class PhysicalDeviceSelector;
}; };
void destroy_instance (Instance instance); // release instance resources void destroy_instance (Instance instance); // release instance resources
class InstanceBuilder class InstanceBuilder {
{
public: public:
detail::Expected<Instance, VkResult> build (); // use builder pattern detail::Expected<Instance, VkResult> build (); // use builder pattern
@ -219,8 +148,7 @@ class InstanceBuilder
InstanceBuilder& add_validation_feature_disable (VkValidationFeatureDisableEXT disable); InstanceBuilder& add_validation_feature_disable (VkValidationFeatureDisableEXT disable);
private: private:
struct InstanceInfo struct InstanceInfo {
{
// VkApplicationInfo // VkApplicationInfo
std::string app_name; std::string app_name;
std::string engine_name; std::string engine_name;
@ -255,21 +183,23 @@ class InstanceBuilder
} info; } info;
}; };
namespace detail const char* to_string_message_severity (VkDebugUtilsMessageSeverityFlagBitsEXT s);
{ const char* to_string_message_type (VkDebugUtilsMessageTypeFlagsEXT s);
struct SurfaceSupportDetails VkResult create_debug_utils_messenger (VkInstance instance,
{ PFN_vkDebugUtilsMessengerCallbackEXT debug_callback,
VkSurfaceCapabilitiesKHR capabilities; VkDebugUtilsMessageSeverityFlagsEXT severity,
std::vector<VkSurfaceFormatKHR> formats; VkDebugUtilsMessageTypeFlagsEXT type,
std::vector<VkPresentModeKHR> present_modes; VkDebugUtilsMessengerEXT* pDebugMessenger);
};
Expected<SurfaceSupportDetails, VkResult> query_surface_support_details ( void destroy_debug_utils_messenger (VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger);
VkPhysicalDevice phys_device, VkSurfaceKHR surface);
struct QueueFamilies static VKAPI_ATTR VkBool32 VKAPI_CALL default_debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
{ VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData);
struct QueueFamilies {
int graphics = -1; int graphics = -1;
int present = -1; int present = -1;
int transfer = -1; int transfer = -1;
@ -281,51 +211,35 @@ struct QueueFamilies
uint32_t count_sparse = 0; uint32_t count_sparse = 0;
}; };
VkFormat find_supported_format (VkPhysicalDevice physical_device, QueueFamilies find_queue_families (VkPhysicalDevice phys_device, VkSurfaceKHR surface);
const std::vector<VkFormat>& candidates,
VkImageTiling tiling,
VkFormatFeatureFlags features);
std::vector<std::string> device_extension_support (VkPhysicalDevice device, std::vector<std::string> extensions);
detail::QueueFamilies find_queue_families (VkPhysicalDevice physDevice, VkSurfaceKHR windowSurface);
bool supports_features (VkPhysicalDeviceFeatures supported, VkPhysicalDeviceFeatures requested);
} // namespace detail
// ---- Physical Device ---- // // ---- Physical Device ---- //
struct PhysicalDevice struct PhysicalDevice {
{
VkPhysicalDevice phys_device = VK_NULL_HANDLE; VkPhysicalDevice phys_device = VK_NULL_HANDLE;
VkSurfaceKHR surface = VK_NULL_HANDLE; VkSurfaceKHR surface = VK_NULL_HANDLE;
VkPhysicalDeviceFeatures physical_device_features{}; VkPhysicalDeviceFeatures features{};
VkPhysicalDeviceProperties physical_device_properties{}; VkPhysicalDeviceProperties properties{};
VkPhysicalDeviceMemoryProperties memory_properties{}; VkPhysicalDeviceMemoryProperties memory_properties{};
detail::QueueFamilies queue_family_properties; QueueFamilies queue_family_properties;
std::vector<std::string> extensions_to_enable; std::vector<std::string> extensions_to_enable;
}; };
namespace detail struct PhysicalDeviceSelector {
{
void populate_physical_device_details (PhysicalDevice physical_device);
} // namespace detail
struct PhysicalDeviceSelector
{
public: public:
PhysicalDeviceSelector (Instance instance); PhysicalDeviceSelector (Instance const& instance);
detail::Expected<PhysicalDevice, VkResult> select (); detail::Expected<PhysicalDevice, VkResult> select ();
PhysicalDeviceSelector& set_surface (VkSurfaceKHR instance); PhysicalDeviceSelector& set_surface (VkSurfaceKHR instance);
PhysicalDeviceSelector& prefer_discrete (bool prefer_discrete = true); PhysicalDeviceSelector& prefer_discrete ();
PhysicalDeviceSelector& prefer_integrated (bool prefer_integrated = true); PhysicalDeviceSelector& prefer_integrated ();
PhysicalDeviceSelector& prefer_virtual_gpu ();
PhysicalDeviceSelector& allow_fallback (bool fallback = true); PhysicalDeviceSelector& allow_fallback (bool fallback = true);
PhysicalDeviceSelector& require_present (bool require = true); PhysicalDeviceSelector& require_present (bool require = true);
@ -344,17 +258,16 @@ struct PhysicalDeviceSelector
PhysicalDeviceSelector& set_required_features (VkPhysicalDeviceFeatures features); PhysicalDeviceSelector& set_required_features (VkPhysicalDeviceFeatures features);
private: private:
struct PhysicalDeviceInfo struct PhysicalDeviceInfo {
{
VkInstance instance = VK_NULL_HANDLE; VkInstance instance = VK_NULL_HANDLE;
VkSurfaceKHR surface = VK_NULL_HANDLE; VkSurfaceKHR surface = VK_NULL_HANDLE;
bool headless = false; bool headless = false;
} info; } info;
struct SelectionCriteria enum PreferredDevice { discrete, integrated, virtual_gpu, cpu, dont_care };
{
bool prefer_discrete = true; struct SelectionCriteria {
bool prefer_integrated = false; PreferredDevice preferred_type = PreferredDevice::discrete;
bool allow_fallback = true; bool allow_fallback = true;
bool require_present = true; bool require_present = true;
bool require_dedicated_transfer_queue = false; bool require_dedicated_transfer_queue = false;
@ -369,23 +282,18 @@ struct PhysicalDeviceSelector
uint32_t desired_version = VK_MAKE_VERSION (1, 0, 0); uint32_t desired_version = VK_MAKE_VERSION (1, 0, 0);
VkPhysicalDeviceFeatures required_features{}; VkPhysicalDeviceFeatures required_features{};
VkPhysicalDeviceFeatures desired_features{};
} criteria; } criteria;
enum class Suitable enum class Suitable { yes, partial, no };
{
yes,
partial,
no
};
Suitable is_device_suitable (VkPhysicalDevice phys_device); Suitable is_device_suitable (VkPhysicalDevice phys_device);
}; };
// ---- Device ---- // // ---- Device ---- //
struct Device struct Device {
{
VkDevice device = VK_NULL_HANDLE; VkDevice device = VK_NULL_HANDLE;
PhysicalDevice physical_device; PhysicalDevice physical_device;
VkSurfaceKHR surface = VK_NULL_HANDLE; VkSurfaceKHR surface = VK_NULL_HANDLE;
@ -393,8 +301,7 @@ struct Device
void destroy_device (Device device); void destroy_device (Device device);
class DeviceBuilder class DeviceBuilder {
{
public: public:
DeviceBuilder (PhysicalDevice device); DeviceBuilder (PhysicalDevice device);
detail::Expected<Device, VkResult> build (); detail::Expected<Device, VkResult> build ();
@ -402,8 +309,7 @@ class DeviceBuilder
template <typename T> DeviceBuilder& add_pNext (T* structure); template <typename T> DeviceBuilder& add_pNext (T* structure);
private: private:
struct DeviceInfo struct DeviceInfo {
{
VkDeviceCreateFlags flags; VkDeviceCreateFlags flags;
std::vector<VkBaseOutStructure*> pNext_chain; std::vector<VkBaseOutStructure*> pNext_chain;
PhysicalDevice physical_device; PhysicalDevice physical_device;
@ -413,11 +319,6 @@ class DeviceBuilder
// ---- Queue ---- // // ---- Queue ---- //
namespace detail
{
VkQueue get_queue (Device const& device, uint32_t family, uint32_t index = 0);
}
uint32_t get_queue_index_present (Device const& device); uint32_t get_queue_index_present (Device const& device);
uint32_t get_queue_index_graphics (Device const& device); uint32_t get_queue_index_graphics (Device const& device);
uint32_t get_queue_index_compute (Device const& device); uint32_t get_queue_index_compute (Device const& device);
@ -430,18 +331,7 @@ detail::Expected<VkQueue, VkResult> get_queue_compute (Device const& device, uin
detail::Expected<VkQueue, VkResult> get_queue_transfer (Device const& device, uint32_t index = 0); detail::Expected<VkQueue, VkResult> get_queue_transfer (Device const& device, uint32_t index = 0);
detail::Expected<VkQueue, VkResult> get_queue_sparse (Device const& device, uint32_t index = 0); detail::Expected<VkQueue, VkResult> get_queue_sparse (Device const& device, uint32_t index = 0);
struct Swapchain {
namespace detail
{
VkSurfaceFormatKHR find_surface_format (std::vector<VkFormat> const& available_formats);
VkPresentModeKHR find_present_mode (std::vector<VkPresentModeKHR> const& available_present_modes,
std::vector<VkPresentModeKHR> const& desired_present_modes);
VkExtent2D find_extent (
VkSurfaceCapabilitiesKHR const& capabilities, uint32_t desired_width, uint32_t desired_height);
} // namespace detail
struct Swapchain
{
VkDevice device = VK_NULL_HANDLE; VkDevice device = VK_NULL_HANDLE;
VkSwapchainKHR swapchain = VK_NULL_HANDLE; VkSwapchainKHR swapchain = VK_NULL_HANDLE;
uint32_t image_count = 0; uint32_t image_count = 0;
@ -454,8 +344,7 @@ detail::Expected<std::vector<VkImage>, VkResult> get_swapchain_images (Swapchain
detail::Expected<std::vector<VkImageView>, VkResult> get_swapchain_image_views ( detail::Expected<std::vector<VkImageView>, VkResult> get_swapchain_image_views (
Swapchain const& swapchain, std::vector<VkImage> const& images); Swapchain const& swapchain, std::vector<VkImage> const& images);
class SwapchainBuilder class SwapchainBuilder {
{
public: public:
SwapchainBuilder (Device const& device); SwapchainBuilder (Device const& device);
SwapchainBuilder (VkPhysicalDevice const physical_device, VkDevice const device, VkSurfaceKHR const surface); SwapchainBuilder (VkPhysicalDevice const physical_device, VkDevice const device, VkSurfaceKHR const surface);
@ -474,9 +363,10 @@ class SwapchainBuilder
SwapchainBuilder& add_fallback_present_mode (VkPresentModeKHR present_mode); SwapchainBuilder& add_fallback_present_mode (VkPresentModeKHR present_mode);
SwapchainBuilder& use_default_present_mode_selection (); SwapchainBuilder& use_default_present_mode_selection ();
private: private:
struct SwapchainInfo struct SwapchainInfo {
{
VkPhysicalDevice physical_device = VK_NULL_HANDLE; VkPhysicalDevice physical_device = VK_NULL_HANDLE;
VkDevice device = VK_NULL_HANDLE; VkDevice device = VK_NULL_HANDLE;
VkSurfaceKHR surface = VK_NULL_HANDLE; VkSurfaceKHR surface = VK_NULL_HANDLE;
@ -485,6 +375,7 @@ class SwapchainBuilder
std::vector<VkPresentModeKHR> desired_present_modes; std::vector<VkPresentModeKHR> desired_present_modes;
uint32_t desired_width = 256; uint32_t desired_width = 256;
uint32_t desired_height = 256; uint32_t desired_height = 256;
std::vector<VkBaseOutStructure*> pNext_elements;
} info; } info;
}; };