diff --git a/.clang-format b/.clang-format index e38d62b..d247dee 100644 --- a/.clang-format +++ b/.clang-format @@ -39,5 +39,4 @@ SpacesInContainerLiterals: false SpacesInParentheses: false Standard: Auto TabWidth: 4 -UseTab: ForIndentation -SortIncludes: false \ No newline at end of file +SortIncludes: false diff --git a/src/VkBootstrap.cpp b/src/VkBootstrap.cpp index 71f2135..d78d686 100644 --- a/src/VkBootstrap.cpp +++ b/src/VkBootstrap.cpp @@ -40,216 +40,216 @@ namespace detail { GenericFeaturesPNextNode::GenericFeaturesPNextNode() { memset(fields, UINT8_MAX, sizeof(VkBool32) * field_capacity); } bool GenericFeaturesPNextNode::match(GenericFeaturesPNextNode const& requested, GenericFeaturesPNextNode const& supported) noexcept { - assert(requested.sType == supported.sType && "Non-matching sTypes in features nodes!"); - for (uint32_t i = 0; i < field_capacity; i++) { - if (requested.fields[i] && !supported.fields[i]) return false; - } - return true; + assert(requested.sType == supported.sType && "Non-matching sTypes in features nodes!"); + for (uint32_t i = 0; i < field_capacity; i++) { + if (requested.fields[i] && !supported.fields[i]) return false; + } + return true; } class VulkanFunctions { - private: - std::mutex init_mutex; - struct VulkanLibrary { + private: + std::mutex init_mutex; + struct VulkanLibrary { #if defined(__linux__) || defined(__APPLE__) - void* library; + void* library; #elif defined(_WIN32) - HMODULE library; + HMODULE library; #endif - PFN_vkGetInstanceProcAddr ptr_vkGetInstanceProcAddr = VK_NULL_HANDLE; + PFN_vkGetInstanceProcAddr ptr_vkGetInstanceProcAddr = VK_NULL_HANDLE; - VulkanLibrary() { + VulkanLibrary() { #if defined(__linux__) - library = dlopen("libvulkan.so.1", RTLD_NOW | RTLD_LOCAL); - if (!library) library = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL); + library = dlopen("libvulkan.so.1", RTLD_NOW | RTLD_LOCAL); + if (!library) library = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL); #elif defined(__APPLE__) - library = dlopen("libvulkan.dylib", RTLD_NOW | RTLD_LOCAL); - if (!library) library = dlopen("libvulkan.1.dylib", RTLD_NOW | RTLD_LOCAL); + library = dlopen("libvulkan.dylib", RTLD_NOW | RTLD_LOCAL); + if (!library) library = dlopen("libvulkan.1.dylib", RTLD_NOW | RTLD_LOCAL); #elif defined(_WIN32) - library = LoadLibrary(TEXT("vulkan-1.dll")); + library = LoadLibrary(TEXT("vulkan-1.dll")); #else - assert(false && "Unsupported platform"); + assert(false && "Unsupported platform"); #endif - if (!library) return; - load_func(ptr_vkGetInstanceProcAddr, "vkGetInstanceProcAddr"); - } + if (!library) return; + load_func(ptr_vkGetInstanceProcAddr, "vkGetInstanceProcAddr"); + } - template void load_func(T& func_dest, const char* func_name) { + template void load_func(T& func_dest, const char* func_name) { #if defined(__linux__) || defined(__APPLE__) - func_dest = reinterpret_cast(dlsym(library, func_name)); + func_dest = reinterpret_cast(dlsym(library, func_name)); #elif defined(_WIN32) - func_dest = reinterpret_cast(GetProcAddress(library, func_name)); + func_dest = reinterpret_cast(GetProcAddress(library, func_name)); #endif - } - void close() { + } + void close() { #if defined(__linux__) || defined(__APPLE__) - dlclose(library); + dlclose(library); #elif defined(_WIN32) - FreeLibrary(library); + FreeLibrary(library); #endif - library = 0; - } - }; - VulkanLibrary& get_vulkan_library() { - static VulkanLibrary lib; - return lib; - } + library = 0; + } + }; + VulkanLibrary& get_vulkan_library() { + static VulkanLibrary lib; + return lib; + } - bool load_vulkan(PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr = nullptr) { - if (fp_vkGetInstanceProcAddr != nullptr) { - ptr_vkGetInstanceProcAddr = fp_vkGetInstanceProcAddr; - return true; - } else { - auto& lib = get_vulkan_library(); - ptr_vkGetInstanceProcAddr = lib.ptr_vkGetInstanceProcAddr; - return lib.library != nullptr && lib.ptr_vkGetInstanceProcAddr != VK_NULL_HANDLE; - } - } + bool load_vulkan(PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr = nullptr) { + if (fp_vkGetInstanceProcAddr != nullptr) { + ptr_vkGetInstanceProcAddr = fp_vkGetInstanceProcAddr; + return true; + } else { + auto& lib = get_vulkan_library(); + ptr_vkGetInstanceProcAddr = lib.ptr_vkGetInstanceProcAddr; + return lib.library != nullptr && lib.ptr_vkGetInstanceProcAddr != VK_NULL_HANDLE; + } + } - void init_pre_instance_funcs() { - fp_vkEnumerateInstanceExtensionProperties = reinterpret_cast( - ptr_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties")); - fp_vkEnumerateInstanceLayerProperties = reinterpret_cast( - ptr_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceLayerProperties")); - fp_vkEnumerateInstanceVersion = reinterpret_cast( - ptr_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceVersion")); - fp_vkCreateInstance = - reinterpret_cast(ptr_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateInstance")); - } + void init_pre_instance_funcs() { + fp_vkEnumerateInstanceExtensionProperties = reinterpret_cast( + ptr_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties")); + fp_vkEnumerateInstanceLayerProperties = reinterpret_cast( + ptr_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceLayerProperties")); + fp_vkEnumerateInstanceVersion = reinterpret_cast( + ptr_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceVersion")); + fp_vkCreateInstance = + reinterpret_cast(ptr_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateInstance")); + } - public: - template void get_inst_proc_addr(T& out_ptr, const char* func_name) { - out_ptr = reinterpret_cast(ptr_vkGetInstanceProcAddr(instance, func_name)); - } + public: + template void get_inst_proc_addr(T& out_ptr, const char* func_name) { + out_ptr = reinterpret_cast(ptr_vkGetInstanceProcAddr(instance, func_name)); + } - template void get_device_proc_addr(VkDevice device, T& out_ptr, const char* func_name) { - out_ptr = reinterpret_cast(fp_vkGetDeviceProcAddr(device, func_name)); - } + template void get_device_proc_addr(VkDevice device, T& out_ptr, const char* func_name) { + out_ptr = reinterpret_cast(fp_vkGetDeviceProcAddr(device, func_name)); + } - PFN_vkGetInstanceProcAddr ptr_vkGetInstanceProcAddr = nullptr; - VkInstance instance = nullptr; + PFN_vkGetInstanceProcAddr ptr_vkGetInstanceProcAddr = nullptr; + VkInstance instance = nullptr; - PFN_vkEnumerateInstanceExtensionProperties fp_vkEnumerateInstanceExtensionProperties = nullptr; - PFN_vkEnumerateInstanceLayerProperties fp_vkEnumerateInstanceLayerProperties = nullptr; - PFN_vkEnumerateInstanceVersion fp_vkEnumerateInstanceVersion = nullptr; - PFN_vkCreateInstance fp_vkCreateInstance = nullptr; - PFN_vkDestroyInstance fp_vkDestroyInstance = nullptr; + PFN_vkEnumerateInstanceExtensionProperties fp_vkEnumerateInstanceExtensionProperties = nullptr; + PFN_vkEnumerateInstanceLayerProperties fp_vkEnumerateInstanceLayerProperties = nullptr; + PFN_vkEnumerateInstanceVersion fp_vkEnumerateInstanceVersion = nullptr; + PFN_vkCreateInstance fp_vkCreateInstance = nullptr; + PFN_vkDestroyInstance fp_vkDestroyInstance = nullptr; - PFN_vkEnumeratePhysicalDevices fp_vkEnumeratePhysicalDevices = nullptr; - PFN_vkGetPhysicalDeviceFeatures fp_vkGetPhysicalDeviceFeatures = nullptr; - PFN_vkGetPhysicalDeviceFeatures2 fp_vkGetPhysicalDeviceFeatures2 = nullptr; - PFN_vkGetPhysicalDeviceFeatures2KHR fp_vkGetPhysicalDeviceFeatures2KHR = nullptr; - PFN_vkGetPhysicalDeviceFormatProperties fp_vkGetPhysicalDeviceFormatProperties = nullptr; - PFN_vkGetPhysicalDeviceImageFormatProperties fp_vkGetPhysicalDeviceImageFormatProperties = nullptr; - PFN_vkGetPhysicalDeviceProperties fp_vkGetPhysicalDeviceProperties = nullptr; - PFN_vkGetPhysicalDeviceProperties2 fp_vkGetPhysicalDeviceProperties2 = nullptr; - PFN_vkGetPhysicalDeviceQueueFamilyProperties fp_vkGetPhysicalDeviceQueueFamilyProperties = nullptr; - PFN_vkGetPhysicalDeviceQueueFamilyProperties2 fp_vkGetPhysicalDeviceQueueFamilyProperties2 = nullptr; - PFN_vkGetPhysicalDeviceMemoryProperties fp_vkGetPhysicalDeviceMemoryProperties = nullptr; - PFN_vkGetPhysicalDeviceFormatProperties2 fp_vkGetPhysicalDeviceFormatProperties2 = nullptr; - PFN_vkGetPhysicalDeviceMemoryProperties2 fp_vkGetPhysicalDeviceMemoryProperties2 = nullptr; + PFN_vkEnumeratePhysicalDevices fp_vkEnumeratePhysicalDevices = nullptr; + PFN_vkGetPhysicalDeviceFeatures fp_vkGetPhysicalDeviceFeatures = nullptr; + PFN_vkGetPhysicalDeviceFeatures2 fp_vkGetPhysicalDeviceFeatures2 = nullptr; + PFN_vkGetPhysicalDeviceFeatures2KHR fp_vkGetPhysicalDeviceFeatures2KHR = nullptr; + PFN_vkGetPhysicalDeviceFormatProperties fp_vkGetPhysicalDeviceFormatProperties = nullptr; + PFN_vkGetPhysicalDeviceImageFormatProperties fp_vkGetPhysicalDeviceImageFormatProperties = nullptr; + PFN_vkGetPhysicalDeviceProperties fp_vkGetPhysicalDeviceProperties = nullptr; + PFN_vkGetPhysicalDeviceProperties2 fp_vkGetPhysicalDeviceProperties2 = nullptr; + PFN_vkGetPhysicalDeviceQueueFamilyProperties fp_vkGetPhysicalDeviceQueueFamilyProperties = nullptr; + PFN_vkGetPhysicalDeviceQueueFamilyProperties2 fp_vkGetPhysicalDeviceQueueFamilyProperties2 = nullptr; + PFN_vkGetPhysicalDeviceMemoryProperties fp_vkGetPhysicalDeviceMemoryProperties = nullptr; + PFN_vkGetPhysicalDeviceFormatProperties2 fp_vkGetPhysicalDeviceFormatProperties2 = nullptr; + PFN_vkGetPhysicalDeviceMemoryProperties2 fp_vkGetPhysicalDeviceMemoryProperties2 = nullptr; - PFN_vkGetDeviceProcAddr fp_vkGetDeviceProcAddr = nullptr; - PFN_vkCreateDevice fp_vkCreateDevice = nullptr; - PFN_vkEnumerateDeviceExtensionProperties fp_vkEnumerateDeviceExtensionProperties = nullptr; + PFN_vkGetDeviceProcAddr fp_vkGetDeviceProcAddr = nullptr; + PFN_vkCreateDevice fp_vkCreateDevice = nullptr; + PFN_vkEnumerateDeviceExtensionProperties fp_vkEnumerateDeviceExtensionProperties = nullptr; - PFN_vkDestroySurfaceKHR fp_vkDestroySurfaceKHR = nullptr; - PFN_vkGetPhysicalDeviceSurfaceSupportKHR fp_vkGetPhysicalDeviceSurfaceSupportKHR = nullptr; - PFN_vkGetPhysicalDeviceSurfaceFormatsKHR fp_vkGetPhysicalDeviceSurfaceFormatsKHR = nullptr; - PFN_vkGetPhysicalDeviceSurfacePresentModesKHR fp_vkGetPhysicalDeviceSurfacePresentModesKHR = nullptr; - PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR fp_vkGetPhysicalDeviceSurfaceCapabilitiesKHR = nullptr; + PFN_vkDestroySurfaceKHR fp_vkDestroySurfaceKHR = nullptr; + PFN_vkGetPhysicalDeviceSurfaceSupportKHR fp_vkGetPhysicalDeviceSurfaceSupportKHR = nullptr; + PFN_vkGetPhysicalDeviceSurfaceFormatsKHR fp_vkGetPhysicalDeviceSurfaceFormatsKHR = nullptr; + PFN_vkGetPhysicalDeviceSurfacePresentModesKHR fp_vkGetPhysicalDeviceSurfacePresentModesKHR = nullptr; + PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR fp_vkGetPhysicalDeviceSurfaceCapabilitiesKHR = nullptr; - bool init_vulkan_funcs(PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr) { - std::lock_guard lg(init_mutex); - if (!load_vulkan(fp_vkGetInstanceProcAddr)) return false; - init_pre_instance_funcs(); - return true; - } + bool init_vulkan_funcs(PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr) { + std::lock_guard lg(init_mutex); + if (!load_vulkan(fp_vkGetInstanceProcAddr)) return false; + init_pre_instance_funcs(); + return true; + } - void init_instance_funcs(VkInstance inst) { - instance = inst; - get_inst_proc_addr(fp_vkDestroyInstance, "vkDestroyInstance"); - get_inst_proc_addr(fp_vkEnumeratePhysicalDevices, "vkEnumeratePhysicalDevices"); - get_inst_proc_addr(fp_vkGetPhysicalDeviceFeatures, "vkGetPhysicalDeviceFeatures"); - get_inst_proc_addr(fp_vkGetPhysicalDeviceFeatures2, "vkGetPhysicalDeviceFeatures2"); - get_inst_proc_addr(fp_vkGetPhysicalDeviceFeatures2KHR, "vkGetPhysicalDeviceFeatures2KHR"); - get_inst_proc_addr(fp_vkGetPhysicalDeviceFormatProperties, "vkGetPhysicalDeviceFormatProperties"); - get_inst_proc_addr(fp_vkGetPhysicalDeviceImageFormatProperties, "vkGetPhysicalDeviceImageFormatProperties"); - get_inst_proc_addr(fp_vkGetPhysicalDeviceProperties, "vkGetPhysicalDeviceProperties"); - get_inst_proc_addr(fp_vkGetPhysicalDeviceProperties2, "vkGetPhysicalDeviceProperties2"); - get_inst_proc_addr(fp_vkGetPhysicalDeviceQueueFamilyProperties, "vkGetPhysicalDeviceQueueFamilyProperties"); - get_inst_proc_addr(fp_vkGetPhysicalDeviceQueueFamilyProperties2, "vkGetPhysicalDeviceQueueFamilyProperties2"); - get_inst_proc_addr(fp_vkGetPhysicalDeviceMemoryProperties, "vkGetPhysicalDeviceMemoryProperties"); - get_inst_proc_addr(fp_vkGetPhysicalDeviceFormatProperties2, "vkGetPhysicalDeviceFormatProperties2"); - get_inst_proc_addr(fp_vkGetPhysicalDeviceMemoryProperties2, "vkGetPhysicalDeviceMemoryProperties2"); + void init_instance_funcs(VkInstance inst) { + instance = inst; + get_inst_proc_addr(fp_vkDestroyInstance, "vkDestroyInstance"); + get_inst_proc_addr(fp_vkEnumeratePhysicalDevices, "vkEnumeratePhysicalDevices"); + get_inst_proc_addr(fp_vkGetPhysicalDeviceFeatures, "vkGetPhysicalDeviceFeatures"); + get_inst_proc_addr(fp_vkGetPhysicalDeviceFeatures2, "vkGetPhysicalDeviceFeatures2"); + get_inst_proc_addr(fp_vkGetPhysicalDeviceFeatures2KHR, "vkGetPhysicalDeviceFeatures2KHR"); + get_inst_proc_addr(fp_vkGetPhysicalDeviceFormatProperties, "vkGetPhysicalDeviceFormatProperties"); + get_inst_proc_addr(fp_vkGetPhysicalDeviceImageFormatProperties, "vkGetPhysicalDeviceImageFormatProperties"); + get_inst_proc_addr(fp_vkGetPhysicalDeviceProperties, "vkGetPhysicalDeviceProperties"); + get_inst_proc_addr(fp_vkGetPhysicalDeviceProperties2, "vkGetPhysicalDeviceProperties2"); + get_inst_proc_addr(fp_vkGetPhysicalDeviceQueueFamilyProperties, "vkGetPhysicalDeviceQueueFamilyProperties"); + get_inst_proc_addr(fp_vkGetPhysicalDeviceQueueFamilyProperties2, "vkGetPhysicalDeviceQueueFamilyProperties2"); + get_inst_proc_addr(fp_vkGetPhysicalDeviceMemoryProperties, "vkGetPhysicalDeviceMemoryProperties"); + get_inst_proc_addr(fp_vkGetPhysicalDeviceFormatProperties2, "vkGetPhysicalDeviceFormatProperties2"); + get_inst_proc_addr(fp_vkGetPhysicalDeviceMemoryProperties2, "vkGetPhysicalDeviceMemoryProperties2"); - get_inst_proc_addr(fp_vkGetDeviceProcAddr, "vkGetDeviceProcAddr"); - get_inst_proc_addr(fp_vkCreateDevice, "vkCreateDevice"); - get_inst_proc_addr(fp_vkEnumerateDeviceExtensionProperties, "vkEnumerateDeviceExtensionProperties"); + get_inst_proc_addr(fp_vkGetDeviceProcAddr, "vkGetDeviceProcAddr"); + get_inst_proc_addr(fp_vkCreateDevice, "vkCreateDevice"); + get_inst_proc_addr(fp_vkEnumerateDeviceExtensionProperties, "vkEnumerateDeviceExtensionProperties"); - get_inst_proc_addr(fp_vkDestroySurfaceKHR, "vkDestroySurfaceKHR"); - get_inst_proc_addr(fp_vkGetPhysicalDeviceSurfaceSupportKHR, "vkGetPhysicalDeviceSurfaceSupportKHR"); - get_inst_proc_addr(fp_vkGetPhysicalDeviceSurfaceFormatsKHR, "vkGetPhysicalDeviceSurfaceFormatsKHR"); - get_inst_proc_addr(fp_vkGetPhysicalDeviceSurfacePresentModesKHR, "vkGetPhysicalDeviceSurfacePresentModesKHR"); - get_inst_proc_addr(fp_vkGetPhysicalDeviceSurfaceCapabilitiesKHR, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); - } + get_inst_proc_addr(fp_vkDestroySurfaceKHR, "vkDestroySurfaceKHR"); + get_inst_proc_addr(fp_vkGetPhysicalDeviceSurfaceSupportKHR, "vkGetPhysicalDeviceSurfaceSupportKHR"); + get_inst_proc_addr(fp_vkGetPhysicalDeviceSurfaceFormatsKHR, "vkGetPhysicalDeviceSurfaceFormatsKHR"); + get_inst_proc_addr(fp_vkGetPhysicalDeviceSurfacePresentModesKHR, "vkGetPhysicalDeviceSurfacePresentModesKHR"); + get_inst_proc_addr(fp_vkGetPhysicalDeviceSurfaceCapabilitiesKHR, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); + } }; VulkanFunctions& vulkan_functions() { - static VulkanFunctions v; - return v; + static VulkanFunctions v; + return v; } // Helper for robustly executing the two-call pattern template auto get_vector(std::vector& out, F&& f, Ts&&... ts) -> VkResult { - uint32_t count = 0; - VkResult err; - do { - err = f(ts..., &count, nullptr); - if (err != VK_SUCCESS) { - return err; - }; - out.resize(count); - err = f(ts..., &count, out.data()); - out.resize(count); - } while (err == VK_INCOMPLETE); - return err; + uint32_t count = 0; + VkResult err; + do { + err = f(ts..., &count, nullptr); + if (err != VK_SUCCESS) { + return err; + }; + out.resize(count); + err = f(ts..., &count, out.data()); + out.resize(count); + } while (err == VK_INCOMPLETE); + return err; } template auto get_vector_noerror(F&& f, Ts&&... ts) -> std::vector { - uint32_t count = 0; - std::vector results; - f(ts..., &count, nullptr); - results.resize(count); - f(ts..., &count, results.data()); - results.resize(count); - return results; + uint32_t count = 0; + std::vector results; + f(ts..., &count, nullptr); + results.resize(count); + f(ts..., &count, results.data()); + results.resize(count); + return results; } } // namespace detail const char* to_string_message_severity(VkDebugUtilsMessageSeverityFlagBitsEXT s) { - switch (s) { - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: - return "VERBOSE"; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: - return "ERROR"; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: - return "WARNING"; - case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: - return "INFO"; - default: - return "UNKNOWN"; - } + switch (s) { + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: + return "VERBOSE"; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + return "ERROR"; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: + return "WARNING"; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: + return "INFO"; + default: + return "UNKNOWN"; + } } const char* to_string_message_type(VkDebugUtilsMessageTypeFlagsEXT s) { - if (s == 7) return "General | Validation | Performance"; - if (s == 6) return "Validation | Performance"; - if (s == 5) return "General | Performance"; - if (s == 4 /*VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT*/) return "Performance"; - if (s == 3) return "General | Validation"; - if (s == 2 /*VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT*/) return "Validation"; - if (s == 1 /*VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT*/) return "General"; - return "Unknown"; + if (s == 7) return "General | Validation | Performance"; + if (s == 6) return "Validation | Performance"; + if (s == 5) return "General | Performance"; + if (s == 4 /*VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT*/) return "Performance"; + if (s == 3) return "General | Validation"; + if (s == 2 /*VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT*/) return "Validation"; + if (s == 1 /*VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT*/) return "General"; + return "Unknown"; } VkResult create_debug_utils_messenger(VkInstance instance, @@ -260,590 +260,590 @@ VkResult create_debug_utils_messenger(VkInstance instance, VkDebugUtilsMessengerEXT* pDebugMessenger, VkAllocationCallbacks* allocation_callbacks) { - if (debug_callback == nullptr) debug_callback = default_debug_callback; - VkDebugUtilsMessengerCreateInfoEXT messengerCreateInfo = {}; - messengerCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; - messengerCreateInfo.pNext = nullptr; - messengerCreateInfo.messageSeverity = severity; - messengerCreateInfo.messageType = type; - messengerCreateInfo.pfnUserCallback = debug_callback; - messengerCreateInfo.pUserData = user_data_pointer; + if (debug_callback == nullptr) debug_callback = default_debug_callback; + VkDebugUtilsMessengerCreateInfoEXT messengerCreateInfo = {}; + messengerCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + messengerCreateInfo.pNext = nullptr; + messengerCreateInfo.messageSeverity = severity; + messengerCreateInfo.messageType = type; + messengerCreateInfo.pfnUserCallback = debug_callback; + messengerCreateInfo.pUserData = user_data_pointer; - PFN_vkCreateDebugUtilsMessengerEXT createMessengerFunc; - detail::vulkan_functions().get_inst_proc_addr(createMessengerFunc, "vkCreateDebugUtilsMessengerEXT"); + PFN_vkCreateDebugUtilsMessengerEXT createMessengerFunc; + detail::vulkan_functions().get_inst_proc_addr(createMessengerFunc, "vkCreateDebugUtilsMessengerEXT"); - if (createMessengerFunc != nullptr) { - return createMessengerFunc(instance, &messengerCreateInfo, allocation_callbacks, pDebugMessenger); - } else { - return VK_ERROR_EXTENSION_NOT_PRESENT; - } + if (createMessengerFunc != nullptr) { + return createMessengerFunc(instance, &messengerCreateInfo, allocation_callbacks, pDebugMessenger); + } else { + return VK_ERROR_EXTENSION_NOT_PRESENT; + } } void destroy_debug_utils_messenger( VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, VkAllocationCallbacks* allocation_callbacks) { - PFN_vkDestroyDebugUtilsMessengerEXT deleteMessengerFunc; - detail::vulkan_functions().get_inst_proc_addr(deleteMessengerFunc, "vkDestroyDebugUtilsMessengerEXT"); + PFN_vkDestroyDebugUtilsMessengerEXT deleteMessengerFunc; + detail::vulkan_functions().get_inst_proc_addr(deleteMessengerFunc, "vkDestroyDebugUtilsMessengerEXT"); - if (deleteMessengerFunc != nullptr) { - deleteMessengerFunc(instance, debugMessenger, allocation_callbacks); - } + if (deleteMessengerFunc != nullptr) { + deleteMessengerFunc(instance, debugMessenger, allocation_callbacks); + } } namespace detail { bool check_layer_supported(std::vector const& 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; + 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 const& available_layers, std::vector const& layer_names) { - bool all_found = true; - for (const auto& layer_name : layer_names) { - bool found = check_layer_supported(available_layers, layer_name); - if (!found) all_found = false; - } - return all_found; + bool all_found = true; + for (const auto& layer_name : layer_names) { + bool found = check_layer_supported(available_layers, layer_name); + if (!found) all_found = false; + } + return all_found; } bool check_extension_supported(std::vector const& available_extensions, const char* extension_name) { - if (!extension_name) return false; - for (const auto& extension_properties : available_extensions) { - if (strcmp(extension_name, extension_properties.extensionName) == 0) { - return true; - } - } - return false; + if (!extension_name) return false; + for (const auto& extension_properties : available_extensions) { + if (strcmp(extension_name, extension_properties.extensionName) == 0) { + return true; + } + } + return false; } bool check_extensions_supported( std::vector const& available_extensions, std::vector const& extension_names) { - bool all_found = true; - for (const auto& extension_name : extension_names) { - bool found = check_extension_supported(available_extensions, extension_name); - if (!found) all_found = false; - } - return all_found; + bool all_found = true; + for (const auto& extension_name : extension_names) { + bool found = check_extension_supported(available_extensions, extension_name); + if (!found) all_found = false; + } + return all_found; } template void setup_pNext_chain(T& structure, std::vector const& structs) { - structure.pNext = nullptr; - if (structs.size() <= 0) return; - for (size_t i = 0; i < structs.size() - 1; i++) { - structs.at(i)->pNext = structs.at(i + 1); - } - structure.pNext = structs.at(0); + structure.pNext = nullptr; + if (structs.size() <= 0) return; + for (size_t i = 0; i < structs.size() - 1; i++) { + structs.at(i)->pNext = structs.at(i + 1); + } + structure.pNext = structs.at(0); } const char* validation_layer_name = "VK_LAYER_KHRONOS_validation"; struct InstanceErrorCategory : std::error_category { - const char* name() const noexcept override { return "vkb_instance"; } - std::string message(int err) const override { return to_string(static_cast(err)); } + const char* name() const noexcept override { return "vkb_instance"; } + std::string message(int err) const override { return to_string(static_cast(err)); } }; const InstanceErrorCategory instance_error_category; struct PhysicalDeviceErrorCategory : std::error_category { - const char* name() const noexcept override { return "vkb_physical_device"; } - std::string message(int err) const override { return to_string(static_cast(err)); } + const char* name() const noexcept override { return "vkb_physical_device"; } + std::string message(int err) const override { return to_string(static_cast(err)); } }; const PhysicalDeviceErrorCategory physical_device_error_category; struct QueueErrorCategory : std::error_category { - const char* name() const noexcept override { return "vkb_queue"; } - std::string message(int err) const override { return to_string(static_cast(err)); } + const char* name() const noexcept override { return "vkb_queue"; } + std::string message(int err) const override { return to_string(static_cast(err)); } }; const QueueErrorCategory queue_error_category; struct DeviceErrorCategory : std::error_category { - const char* name() const noexcept override { return "vkb_device"; } - std::string message(int err) const override { return to_string(static_cast(err)); } + const char* name() const noexcept override { return "vkb_device"; } + std::string message(int err) const override { return to_string(static_cast(err)); } }; const DeviceErrorCategory device_error_category; struct SwapchainErrorCategory : std::error_category { - const char* name() const noexcept override { return "vbk_swapchain"; } - std::string message(int err) const override { return to_string(static_cast(err)); } + const char* name() const noexcept override { return "vbk_swapchain"; } + std::string message(int err) const override { return to_string(static_cast(err)); } }; const SwapchainErrorCategory swapchain_error_category; } // namespace detail std::error_code make_error_code(InstanceError instance_error) { - return { static_cast(instance_error), detail::instance_error_category }; + return { static_cast(instance_error), detail::instance_error_category }; } std::error_code make_error_code(PhysicalDeviceError physical_device_error) { - return { static_cast(physical_device_error), detail::physical_device_error_category }; + return { static_cast(physical_device_error), detail::physical_device_error_category }; } std::error_code make_error_code(QueueError queue_error) { - return { static_cast(queue_error), detail::queue_error_category }; + return { static_cast(queue_error), detail::queue_error_category }; } std::error_code make_error_code(DeviceError device_error) { - return { static_cast(device_error), detail::device_error_category }; + return { static_cast(device_error), detail::device_error_category }; } std::error_code make_error_code(SwapchainError swapchain_error) { - return { static_cast(swapchain_error), detail::swapchain_error_category }; + return { static_cast(swapchain_error), detail::swapchain_error_category }; } #define CASE_TO_STRING(CATEGORY, TYPE) \ - case CATEGORY::TYPE: \ - return #TYPE; + case CATEGORY::TYPE: \ + return #TYPE; const char* to_string(InstanceError err) { - switch (err) { - CASE_TO_STRING(InstanceError, vulkan_unavailable) - CASE_TO_STRING(InstanceError, vulkan_version_unavailable) - CASE_TO_STRING(InstanceError, vulkan_version_1_1_unavailable) - CASE_TO_STRING(InstanceError, vulkan_version_1_2_unavailable) - CASE_TO_STRING(InstanceError, failed_create_debug_messenger) - CASE_TO_STRING(InstanceError, failed_create_instance) - CASE_TO_STRING(InstanceError, requested_layers_not_present) - CASE_TO_STRING(InstanceError, requested_extensions_not_present) - CASE_TO_STRING(InstanceError, windowing_extensions_not_present) - default: - return ""; - } + switch (err) { + CASE_TO_STRING(InstanceError, vulkan_unavailable) + CASE_TO_STRING(InstanceError, vulkan_version_unavailable) + CASE_TO_STRING(InstanceError, vulkan_version_1_1_unavailable) + CASE_TO_STRING(InstanceError, vulkan_version_1_2_unavailable) + CASE_TO_STRING(InstanceError, failed_create_debug_messenger) + CASE_TO_STRING(InstanceError, failed_create_instance) + CASE_TO_STRING(InstanceError, requested_layers_not_present) + CASE_TO_STRING(InstanceError, requested_extensions_not_present) + CASE_TO_STRING(InstanceError, windowing_extensions_not_present) + default: + return ""; + } } const char* to_string(PhysicalDeviceError err) { - switch (err) { - CASE_TO_STRING(PhysicalDeviceError, no_surface_provided) - CASE_TO_STRING(PhysicalDeviceError, failed_enumerate_physical_devices) - CASE_TO_STRING(PhysicalDeviceError, no_physical_devices_found) - CASE_TO_STRING(PhysicalDeviceError, no_suitable_device) - default: - return ""; - } + switch (err) { + CASE_TO_STRING(PhysicalDeviceError, no_surface_provided) + CASE_TO_STRING(PhysicalDeviceError, failed_enumerate_physical_devices) + CASE_TO_STRING(PhysicalDeviceError, no_physical_devices_found) + CASE_TO_STRING(PhysicalDeviceError, no_suitable_device) + default: + return ""; + } } const char* to_string(QueueError err) { - switch (err) { - CASE_TO_STRING(QueueError, present_unavailable) - CASE_TO_STRING(QueueError, graphics_unavailable) - CASE_TO_STRING(QueueError, compute_unavailable) - CASE_TO_STRING(QueueError, transfer_unavailable) - CASE_TO_STRING(QueueError, queue_index_out_of_range) - CASE_TO_STRING(QueueError, invalid_queue_family_index) - default: - return ""; - } + switch (err) { + CASE_TO_STRING(QueueError, present_unavailable) + CASE_TO_STRING(QueueError, graphics_unavailable) + CASE_TO_STRING(QueueError, compute_unavailable) + CASE_TO_STRING(QueueError, transfer_unavailable) + CASE_TO_STRING(QueueError, queue_index_out_of_range) + CASE_TO_STRING(QueueError, invalid_queue_family_index) + default: + return ""; + } } const char* to_string(DeviceError err) { - switch (err) { - CASE_TO_STRING(DeviceError, failed_create_device) - default: - return ""; - } + switch (err) { + CASE_TO_STRING(DeviceError, failed_create_device) + default: + return ""; + } } const char* to_string(SwapchainError err) { - switch (err) { - CASE_TO_STRING(SwapchainError, surface_handle_not_provided) - CASE_TO_STRING(SwapchainError, failed_query_surface_support_details) - CASE_TO_STRING(SwapchainError, failed_create_swapchain) - CASE_TO_STRING(SwapchainError, failed_get_swapchain_images) - CASE_TO_STRING(SwapchainError, failed_create_swapchain_image_views) - CASE_TO_STRING(SwapchainError, required_min_image_count_too_low) - CASE_TO_STRING(SwapchainError, required_usage_not_supported) - default: - return ""; - } + switch (err) { + CASE_TO_STRING(SwapchainError, surface_handle_not_provided) + CASE_TO_STRING(SwapchainError, failed_query_surface_support_details) + CASE_TO_STRING(SwapchainError, failed_create_swapchain) + CASE_TO_STRING(SwapchainError, failed_get_swapchain_images) + CASE_TO_STRING(SwapchainError, failed_create_swapchain_image_views) + CASE_TO_STRING(SwapchainError, required_min_image_count_too_low) + CASE_TO_STRING(SwapchainError, required_usage_not_supported) + default: + return ""; + } } Result SystemInfo::get_system_info() { - if (!detail::vulkan_functions().init_vulkan_funcs(nullptr)) { - return make_error_code(InstanceError::vulkan_unavailable); - } - return SystemInfo(); + if (!detail::vulkan_functions().init_vulkan_funcs(nullptr)) { + return make_error_code(InstanceError::vulkan_unavailable); + } + return SystemInfo(); } Result SystemInfo::get_system_info(PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr) { - // Using externally provided function pointers, assume the loader is available - if (!detail::vulkan_functions().init_vulkan_funcs(fp_vkGetInstanceProcAddr)) { - return make_error_code(InstanceError::vulkan_unavailable); - } - return SystemInfo(); + // Using externally provided function pointers, assume the loader is available + if (!detail::vulkan_functions().init_vulkan_funcs(fp_vkGetInstanceProcAddr)) { + return make_error_code(InstanceError::vulkan_unavailable); + } + return SystemInfo(); } SystemInfo::SystemInfo() { - auto available_layers_ret = detail::get_vector( - this->available_layers, detail::vulkan_functions().fp_vkEnumerateInstanceLayerProperties); - if (available_layers_ret != VK_SUCCESS) { - this->available_layers.clear(); - } + auto available_layers_ret = detail::get_vector( + this->available_layers, detail::vulkan_functions().fp_vkEnumerateInstanceLayerProperties); + if (available_layers_ret != VK_SUCCESS) { + this->available_layers.clear(); + } - for (auto& layer : this->available_layers) - if (strcmp(layer.layerName, detail::validation_layer_name) == 0) validation_layers_available = true; + for (auto& layer : this->available_layers) + if (strcmp(layer.layerName, detail::validation_layer_name) == 0) validation_layers_available = true; - auto available_extensions_ret = detail::get_vector( - this->available_extensions, detail::vulkan_functions().fp_vkEnumerateInstanceExtensionProperties, nullptr); - if (available_extensions_ret != VK_SUCCESS) { - this->available_extensions.clear(); - } + auto available_extensions_ret = detail::get_vector( + this->available_extensions, detail::vulkan_functions().fp_vkEnumerateInstanceExtensionProperties, nullptr); + if (available_extensions_ret != VK_SUCCESS) { + this->available_extensions.clear(); + } - for (auto& ext : this->available_extensions) { - if (strcmp(ext.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) { - debug_utils_available = true; - } - } + for (auto& ext : this->available_extensions) { + if (strcmp(ext.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) { + debug_utils_available = true; + } + } - for (auto& layer : this->available_layers) { - std::vector layer_extensions; - auto layer_extensions_ret = detail::get_vector( - layer_extensions, detail::vulkan_functions().fp_vkEnumerateInstanceExtensionProperties, layer.layerName); - if (layer_extensions_ret == VK_SUCCESS) { - this->available_extensions.insert( - this->available_extensions.end(), layer_extensions.begin(), layer_extensions.end()); - for (auto& ext : layer_extensions) { - if (strcmp(ext.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) { - debug_utils_available = true; - } - } - } - } + for (auto& layer : this->available_layers) { + std::vector layer_extensions; + auto layer_extensions_ret = detail::get_vector( + layer_extensions, detail::vulkan_functions().fp_vkEnumerateInstanceExtensionProperties, layer.layerName); + if (layer_extensions_ret == VK_SUCCESS) { + this->available_extensions.insert( + this->available_extensions.end(), layer_extensions.begin(), layer_extensions.end()); + for (auto& ext : layer_extensions) { + if (strcmp(ext.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) { + debug_utils_available = true; + } + } + } + } } bool SystemInfo::is_extension_available(const char* extension_name) const { - if (!extension_name) return false; - return detail::check_extension_supported(available_extensions, 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) const { - if (!layer_name) return false; - return detail::check_layer_supported(available_layers, layer_name); + if (!layer_name) return false; + return detail::check_layer_supported(available_layers, layer_name); } void destroy_surface(Instance instance, VkSurfaceKHR surface) { - if (instance.instance != VK_NULL_HANDLE && surface != VK_NULL_HANDLE) { - detail::vulkan_functions().fp_vkDestroySurfaceKHR(instance.instance, surface, instance.allocation_callbacks); - } + if (instance.instance != VK_NULL_HANDLE && surface != VK_NULL_HANDLE) { + detail::vulkan_functions().fp_vkDestroySurfaceKHR(instance.instance, surface, instance.allocation_callbacks); + } } void destroy_surface(VkInstance instance, VkSurfaceKHR surface, VkAllocationCallbacks* callbacks) { - if (instance != VK_NULL_HANDLE && surface != VK_NULL_HANDLE) { - detail::vulkan_functions().fp_vkDestroySurfaceKHR(instance, surface, callbacks); - } + if (instance != VK_NULL_HANDLE && surface != VK_NULL_HANDLE) { + detail::vulkan_functions().fp_vkDestroySurfaceKHR(instance, surface, callbacks); + } } void destroy_instance(Instance instance) { - if (instance.instance != VK_NULL_HANDLE) { - if (instance.debug_messenger != VK_NULL_HANDLE) - destroy_debug_utils_messenger(instance.instance, instance.debug_messenger, instance.allocation_callbacks); - detail::vulkan_functions().fp_vkDestroyInstance(instance.instance, instance.allocation_callbacks); - } + if (instance.instance != VK_NULL_HANDLE) { + if (instance.debug_messenger != VK_NULL_HANDLE) + destroy_debug_utils_messenger(instance.instance, instance.debug_messenger, instance.allocation_callbacks); + detail::vulkan_functions().fp_vkDestroyInstance(instance.instance, instance.allocation_callbacks); + } } Instance::operator VkInstance() const { return this->instance; } InstanceBuilder::InstanceBuilder(PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr) { - info.fp_vkGetInstanceProcAddr = fp_vkGetInstanceProcAddr; + info.fp_vkGetInstanceProcAddr = fp_vkGetInstanceProcAddr; } InstanceBuilder::InstanceBuilder() {} Result InstanceBuilder::build() const { - auto sys_info_ret = SystemInfo::get_system_info(info.fp_vkGetInstanceProcAddr); - if (!sys_info_ret) return sys_info_ret.error(); - auto system = sys_info_ret.value(); + auto sys_info_ret = SystemInfo::get_system_info(info.fp_vkGetInstanceProcAddr); + if (!sys_info_ret) return sys_info_ret.error(); + auto system = sys_info_ret.value(); - uint32_t instance_version = VKB_VK_API_VERSION_1_0; + uint32_t instance_version = VKB_VK_API_VERSION_1_0; - if (info.minimum_instance_version > VKB_VK_API_VERSION_1_0 || info.required_api_version > VKB_VK_API_VERSION_1_0 || - info.desired_api_version > VKB_VK_API_VERSION_1_0) { - PFN_vkEnumerateInstanceVersion pfn_vkEnumerateInstanceVersion = detail::vulkan_functions().fp_vkEnumerateInstanceVersion; + if (info.minimum_instance_version > VKB_VK_API_VERSION_1_0 || info.required_api_version > VKB_VK_API_VERSION_1_0 || + info.desired_api_version > VKB_VK_API_VERSION_1_0) { + PFN_vkEnumerateInstanceVersion pfn_vkEnumerateInstanceVersion = detail::vulkan_functions().fp_vkEnumerateInstanceVersion; - if (pfn_vkEnumerateInstanceVersion != nullptr) { - VkResult res = pfn_vkEnumerateInstanceVersion(&instance_version); - // Should always return VK_SUCCESS - if (res != VK_SUCCESS && info.required_api_version > 0) - return make_error_code(InstanceError::vulkan_version_unavailable); - } - if (pfn_vkEnumerateInstanceVersion == nullptr || instance_version < info.minimum_instance_version || - (info.minimum_instance_version == 0 && instance_version < info.required_api_version)) { - if (VK_VERSION_MINOR(info.required_api_version) == 2) - return make_error_code(InstanceError::vulkan_version_1_2_unavailable); - else if (VK_VERSION_MINOR(info.required_api_version)) - return make_error_code(InstanceError::vulkan_version_1_1_unavailable); - else - return make_error_code(InstanceError::vulkan_version_unavailable); - } - } + if (pfn_vkEnumerateInstanceVersion != nullptr) { + VkResult res = pfn_vkEnumerateInstanceVersion(&instance_version); + // Should always return VK_SUCCESS + if (res != VK_SUCCESS && info.required_api_version > 0) + return make_error_code(InstanceError::vulkan_version_unavailable); + } + if (pfn_vkEnumerateInstanceVersion == nullptr || instance_version < info.minimum_instance_version || + (info.minimum_instance_version == 0 && instance_version < info.required_api_version)) { + if (VK_VERSION_MINOR(info.required_api_version) == 2) + return make_error_code(InstanceError::vulkan_version_1_2_unavailable); + else if (VK_VERSION_MINOR(info.required_api_version)) + return make_error_code(InstanceError::vulkan_version_1_1_unavailable); + else + return make_error_code(InstanceError::vulkan_version_unavailable); + } + } - uint32_t api_version = instance_version < VKB_VK_API_VERSION_1_1 ? instance_version : info.required_api_version; + uint32_t api_version = instance_version < VKB_VK_API_VERSION_1_1 ? instance_version : info.required_api_version; - if (info.desired_api_version > VKB_VK_API_VERSION_1_0 && instance_version >= info.desired_api_version) { - instance_version = info.desired_api_version; - api_version = info.desired_api_version; - } + if (info.desired_api_version > VKB_VK_API_VERSION_1_0 && instance_version >= info.desired_api_version) { + instance_version = info.desired_api_version; + api_version = info.desired_api_version; + } - VkApplicationInfo app_info = {}; - app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - app_info.pNext = nullptr; - app_info.pApplicationName = info.app_name != nullptr ? info.app_name : ""; - app_info.applicationVersion = info.application_version; - app_info.pEngineName = info.engine_name != nullptr ? info.engine_name : ""; - app_info.engineVersion = info.engine_version; - app_info.apiVersion = api_version; + VkApplicationInfo app_info = {}; + app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + app_info.pNext = nullptr; + app_info.pApplicationName = info.app_name != nullptr ? info.app_name : ""; + app_info.applicationVersion = info.application_version; + app_info.pEngineName = info.engine_name != nullptr ? info.engine_name : ""; + app_info.engineVersion = info.engine_version; + app_info.apiVersion = api_version; - std::vector extensions; - std::vector layers; + std::vector extensions; + std::vector layers; - for (auto& ext : info.extensions) - extensions.push_back(ext); - if (info.debug_callback != nullptr && info.use_debug_messenger && system.debug_utils_available) { - extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); - } - bool properties2_ext_enabled = - api_version < VKB_VK_API_VERSION_1_1 && detail::check_extension_supported(system.available_extensions, - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - if (properties2_ext_enabled) { - extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); - } + for (auto& ext : info.extensions) + extensions.push_back(ext); + if (info.debug_callback != nullptr && info.use_debug_messenger && system.debug_utils_available) { + extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + } + bool properties2_ext_enabled = + api_version < VKB_VK_API_VERSION_1_1 && detail::check_extension_supported(system.available_extensions, + VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + if (properties2_ext_enabled) { + extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); + } #if defined(VK_KHR_portability_enumeration) - bool portability_enumeration_support = - detail::check_extension_supported(system.available_extensions, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); - if (portability_enumeration_support) { - extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); - } + bool portability_enumeration_support = + detail::check_extension_supported(system.available_extensions, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + if (portability_enumeration_support) { + extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + } #else - bool portability_enumeration_support = false; + bool portability_enumeration_support = false; #endif - if (!info.headless_context) { - auto check_add_window_ext = [&](const char* name) -> bool { - if (!detail::check_extension_supported(system.available_extensions, name)) return false; - extensions.push_back(name); - return true; - }; - bool khr_surface_added = check_add_window_ext("VK_KHR_surface"); + if (!info.headless_context) { + auto check_add_window_ext = [&](const char* name) -> bool { + if (!detail::check_extension_supported(system.available_extensions, name)) return false; + extensions.push_back(name); + return true; + }; + bool khr_surface_added = check_add_window_ext("VK_KHR_surface"); #if defined(_WIN32) - bool added_window_exts = check_add_window_ext("VK_KHR_win32_surface"); + bool added_window_exts = check_add_window_ext("VK_KHR_win32_surface"); #elif defined(__ANDROID__) - bool added_window_exts = check_add_window_ext("VK_KHR_android_surface"); + bool added_window_exts = check_add_window_ext("VK_KHR_android_surface"); #elif defined(_DIRECT2DISPLAY) - bool added_window_exts = check_add_window_ext("VK_KHR_display"); + bool added_window_exts = check_add_window_ext("VK_KHR_display"); #elif defined(__linux__) - // make sure all three calls to check_add_window_ext, don't allow short circuiting - bool added_window_exts = check_add_window_ext("VK_KHR_xcb_surface"); - added_window_exts = check_add_window_ext("VK_KHR_xlib_surface") || added_window_exts; - added_window_exts = check_add_window_ext("VK_KHR_wayland_surface") || added_window_exts; + // make sure all three calls to check_add_window_ext, don't allow short circuiting + bool added_window_exts = check_add_window_ext("VK_KHR_xcb_surface"); + added_window_exts = check_add_window_ext("VK_KHR_xlib_surface") || added_window_exts; + added_window_exts = check_add_window_ext("VK_KHR_wayland_surface") || added_window_exts; #elif defined(__APPLE__) - bool added_window_exts = check_add_window_ext("VK_EXT_metal_surface"); + bool added_window_exts = check_add_window_ext("VK_EXT_metal_surface"); #endif - if (!khr_surface_added || !added_window_exts) - return make_error_code(InstanceError::windowing_extensions_not_present); - } - bool all_extensions_supported = detail::check_extensions_supported(system.available_extensions, extensions); - if (!all_extensions_supported) { - return make_error_code(InstanceError::requested_extensions_not_present); - } + if (!khr_surface_added || !added_window_exts) + return make_error_code(InstanceError::windowing_extensions_not_present); + } + bool all_extensions_supported = detail::check_extensions_supported(system.available_extensions, extensions); + if (!all_extensions_supported) { + return make_error_code(InstanceError::requested_extensions_not_present); + } - for (auto& layer : info.layers) - layers.push_back(layer); + for (auto& layer : info.layers) + layers.push_back(layer); - if (info.enable_validation_layers || (info.request_validation_layers && system.validation_layers_available)) { - layers.push_back(detail::validation_layer_name); - } - bool all_layers_supported = detail::check_layers_supported(system.available_layers, layers); - if (!all_layers_supported) { - return make_error_code(InstanceError::requested_layers_not_present); - } + if (info.enable_validation_layers || (info.request_validation_layers && system.validation_layers_available)) { + layers.push_back(detail::validation_layer_name); + } + bool all_layers_supported = detail::check_layers_supported(system.available_layers, layers); + if (!all_layers_supported) { + return make_error_code(InstanceError::requested_layers_not_present); + } - std::vector pNext_chain; + std::vector pNext_chain; - VkDebugUtilsMessengerCreateInfoEXT messengerCreateInfo = {}; - if (info.use_debug_messenger) { - messengerCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; - messengerCreateInfo.pNext = nullptr; - messengerCreateInfo.messageSeverity = info.debug_message_severity; - messengerCreateInfo.messageType = info.debug_message_type; - messengerCreateInfo.pfnUserCallback = info.debug_callback; - messengerCreateInfo.pUserData = info.debug_user_data_pointer; - pNext_chain.push_back(reinterpret_cast(&messengerCreateInfo)); - } + VkDebugUtilsMessengerCreateInfoEXT messengerCreateInfo = {}; + if (info.use_debug_messenger) { + messengerCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + messengerCreateInfo.pNext = nullptr; + messengerCreateInfo.messageSeverity = info.debug_message_severity; + messengerCreateInfo.messageType = info.debug_message_type; + messengerCreateInfo.pfnUserCallback = info.debug_callback; + messengerCreateInfo.pUserData = info.debug_user_data_pointer; + pNext_chain.push_back(reinterpret_cast(&messengerCreateInfo)); + } - VkValidationFeaturesEXT features{}; - if (info.enabled_validation_features.size() != 0 || info.disabled_validation_features.size()) { - features.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT; - features.pNext = nullptr; - features.enabledValidationFeatureCount = static_cast(info.enabled_validation_features.size()); - features.pEnabledValidationFeatures = info.enabled_validation_features.data(); - features.disabledValidationFeatureCount = static_cast(info.disabled_validation_features.size()); - features.pDisabledValidationFeatures = info.disabled_validation_features.data(); - pNext_chain.push_back(reinterpret_cast(&features)); - } + VkValidationFeaturesEXT features{}; + if (info.enabled_validation_features.size() != 0 || info.disabled_validation_features.size()) { + features.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT; + features.pNext = nullptr; + features.enabledValidationFeatureCount = static_cast(info.enabled_validation_features.size()); + features.pEnabledValidationFeatures = info.enabled_validation_features.data(); + features.disabledValidationFeatureCount = static_cast(info.disabled_validation_features.size()); + features.pDisabledValidationFeatures = info.disabled_validation_features.data(); + pNext_chain.push_back(reinterpret_cast(&features)); + } - VkValidationFlagsEXT checks{}; - if (info.disabled_validation_checks.size() != 0) { - checks.sType = VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT; - checks.pNext = nullptr; - checks.disabledValidationCheckCount = static_cast(info.disabled_validation_checks.size()); - checks.pDisabledValidationChecks = info.disabled_validation_checks.data(); - pNext_chain.push_back(reinterpret_cast(&checks)); - } + VkValidationFlagsEXT checks{}; + if (info.disabled_validation_checks.size() != 0) { + checks.sType = VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT; + checks.pNext = nullptr; + checks.disabledValidationCheckCount = static_cast(info.disabled_validation_checks.size()); + checks.pDisabledValidationChecks = info.disabled_validation_checks.data(); + pNext_chain.push_back(reinterpret_cast(&checks)); + } - VkInstanceCreateInfo instance_create_info = {}; - instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - detail::setup_pNext_chain(instance_create_info, pNext_chain); + VkInstanceCreateInfo instance_create_info = {}; + instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + detail::setup_pNext_chain(instance_create_info, pNext_chain); #if !defined(NDEBUG) - for (auto& node : pNext_chain) { - assert(node->sType != VK_STRUCTURE_TYPE_APPLICATION_INFO); - } + for (auto& node : pNext_chain) { + assert(node->sType != VK_STRUCTURE_TYPE_APPLICATION_INFO); + } #endif - instance_create_info.flags = info.flags; - instance_create_info.pApplicationInfo = &app_info; - instance_create_info.enabledExtensionCount = static_cast(extensions.size()); - instance_create_info.ppEnabledExtensionNames = extensions.data(); - instance_create_info.enabledLayerCount = static_cast(layers.size()); - instance_create_info.ppEnabledLayerNames = layers.data(); + instance_create_info.flags = info.flags; + instance_create_info.pApplicationInfo = &app_info; + instance_create_info.enabledExtensionCount = static_cast(extensions.size()); + instance_create_info.ppEnabledExtensionNames = extensions.data(); + instance_create_info.enabledLayerCount = static_cast(layers.size()); + instance_create_info.ppEnabledLayerNames = layers.data(); #if defined(VK_KHR_portability_enumeration) - if (portability_enumeration_support) { - instance_create_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; - } + if (portability_enumeration_support) { + instance_create_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + } #endif - Instance instance; - VkResult res = - detail::vulkan_functions().fp_vkCreateInstance(&instance_create_info, info.allocation_callbacks, &instance.instance); - if (res != VK_SUCCESS) return Result(InstanceError::failed_create_instance, res); + Instance instance; + VkResult res = + detail::vulkan_functions().fp_vkCreateInstance(&instance_create_info, info.allocation_callbacks, &instance.instance); + if (res != VK_SUCCESS) return Result(InstanceError::failed_create_instance, res); - detail::vulkan_functions().init_instance_funcs(instance.instance); + detail::vulkan_functions().init_instance_funcs(instance.instance); - if (info.use_debug_messenger) { - res = create_debug_utils_messenger(instance.instance, - info.debug_callback, - info.debug_message_severity, - info.debug_message_type, - info.debug_user_data_pointer, - &instance.debug_messenger, - info.allocation_callbacks); - if (res != VK_SUCCESS) { - return Result(InstanceError::failed_create_debug_messenger, res); - } - } + if (info.use_debug_messenger) { + res = create_debug_utils_messenger(instance.instance, + info.debug_callback, + info.debug_message_severity, + info.debug_message_type, + info.debug_user_data_pointer, + &instance.debug_messenger, + info.allocation_callbacks); + if (res != VK_SUCCESS) { + return Result(InstanceError::failed_create_debug_messenger, res); + } + } - instance.headless = info.headless_context; - instance.properties2_ext_enabled = properties2_ext_enabled; - instance.allocation_callbacks = info.allocation_callbacks; - instance.instance_version = instance_version; - instance.api_version = api_version; - instance.fp_vkGetInstanceProcAddr = detail::vulkan_functions().ptr_vkGetInstanceProcAddr; - instance.fp_vkGetDeviceProcAddr = detail::vulkan_functions().fp_vkGetDeviceProcAddr; - return instance; + instance.headless = info.headless_context; + instance.properties2_ext_enabled = properties2_ext_enabled; + instance.allocation_callbacks = info.allocation_callbacks; + instance.instance_version = instance_version; + instance.api_version = api_version; + instance.fp_vkGetInstanceProcAddr = detail::vulkan_functions().ptr_vkGetInstanceProcAddr; + instance.fp_vkGetDeviceProcAddr = detail::vulkan_functions().fp_vkGetDeviceProcAddr; + return instance; } InstanceBuilder& InstanceBuilder::set_app_name(const char* app_name) { - if (!app_name) return *this; - info.app_name = app_name; - return *this; + 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; + if (!engine_name) return *this; + info.engine_name = engine_name; + return *this; } InstanceBuilder& InstanceBuilder::set_app_version(uint32_t app_version) { - info.application_version = app_version; - return *this; + info.application_version = app_version; + return *this; } InstanceBuilder& InstanceBuilder::set_app_version(uint32_t major, uint32_t minor, uint32_t patch) { - info.application_version = VKB_MAKE_VK_VERSION(0, major, minor, patch); - return *this; + info.application_version = VKB_MAKE_VK_VERSION(0, major, minor, patch); + return *this; } InstanceBuilder& InstanceBuilder::set_engine_version(uint32_t engine_version) { - info.engine_version = engine_version; - return *this; + info.engine_version = engine_version; + return *this; } InstanceBuilder& InstanceBuilder::set_engine_version(uint32_t major, uint32_t minor, uint32_t patch) { - info.engine_version = VKB_MAKE_VK_VERSION(0, major, minor, patch); - return *this; + info.engine_version = VKB_MAKE_VK_VERSION(0, major, minor, patch); + return *this; } InstanceBuilder& InstanceBuilder::require_api_version(uint32_t required_api_version) { - info.required_api_version = required_api_version; - return *this; + info.required_api_version = required_api_version; + return *this; } InstanceBuilder& InstanceBuilder::require_api_version(uint32_t major, uint32_t minor, uint32_t patch) { - info.required_api_version = VKB_MAKE_VK_VERSION(0, major, minor, patch); - return *this; + info.required_api_version = VKB_MAKE_VK_VERSION(0, major, minor, patch); + return *this; } InstanceBuilder& InstanceBuilder::set_minimum_instance_version(uint32_t minimum_instance_version) { - info.minimum_instance_version = minimum_instance_version; - return *this; + info.minimum_instance_version = minimum_instance_version; + return *this; } InstanceBuilder& InstanceBuilder::set_minimum_instance_version(uint32_t major, uint32_t minor, uint32_t patch) { - info.minimum_instance_version = VKB_MAKE_VK_VERSION(0, major, minor, patch); - return *this; + info.minimum_instance_version = VKB_MAKE_VK_VERSION(0, major, minor, patch); + return *this; } InstanceBuilder& InstanceBuilder::desire_api_version(uint32_t preferred_vulkan_version) { - info.desired_api_version = preferred_vulkan_version; - return *this; + info.desired_api_version = preferred_vulkan_version; + return *this; } InstanceBuilder& InstanceBuilder::desire_api_version(uint32_t major, uint32_t minor, uint32_t patch) { - info.desired_api_version = VKB_MAKE_VK_VERSION(0, major, minor, patch); - return *this; + info.desired_api_version = VKB_MAKE_VK_VERSION(0, major, minor, patch); + return *this; } InstanceBuilder& InstanceBuilder::enable_layer(const char* layer_name) { - if (!layer_name) return *this; - info.layers.push_back(layer_name); - return *this; + if (!layer_name) return *this; + info.layers.push_back(layer_name); + return *this; } InstanceBuilder& InstanceBuilder::enable_extension(const char* extension_name) { - if (!extension_name) return *this; - info.extensions.push_back(extension_name); - return *this; + if (!extension_name) return *this; + info.extensions.push_back(extension_name); + return *this; } InstanceBuilder& InstanceBuilder::enable_validation_layers(bool enable_validation) { - info.enable_validation_layers = enable_validation; - return *this; + info.enable_validation_layers = enable_validation; + return *this; } InstanceBuilder& InstanceBuilder::request_validation_layers(bool enable_validation) { - info.request_validation_layers = enable_validation; - return *this; + info.request_validation_layers = enable_validation; + return *this; } InstanceBuilder& InstanceBuilder::use_default_debug_messenger() { - info.use_debug_messenger = true; - info.debug_callback = default_debug_callback; - return *this; + info.use_debug_messenger = true; + info.debug_callback = default_debug_callback; + return *this; } InstanceBuilder& InstanceBuilder::set_debug_callback(PFN_vkDebugUtilsMessengerCallbackEXT callback) { - info.use_debug_messenger = true; - info.debug_callback = callback; - return *this; + info.use_debug_messenger = true; + info.debug_callback = callback; + return *this; } InstanceBuilder& InstanceBuilder::set_debug_callback_user_data_pointer(void* user_data_pointer) { - info.debug_user_data_pointer = user_data_pointer; - return *this; + info.debug_user_data_pointer = user_data_pointer; + return *this; } InstanceBuilder& InstanceBuilder::set_headless(bool headless) { - info.headless_context = headless; - return *this; + info.headless_context = headless; + return *this; } InstanceBuilder& InstanceBuilder::set_debug_messenger_severity(VkDebugUtilsMessageSeverityFlagsEXT severity) { - info.debug_message_severity = severity; - return *this; + info.debug_message_severity = severity; + return *this; } InstanceBuilder& InstanceBuilder::add_debug_messenger_severity(VkDebugUtilsMessageSeverityFlagsEXT severity) { - info.debug_message_severity = info.debug_message_severity | severity; - return *this; + info.debug_message_severity = info.debug_message_severity | severity; + return *this; } InstanceBuilder& InstanceBuilder::set_debug_messenger_type(VkDebugUtilsMessageTypeFlagsEXT type) { - info.debug_message_type = type; - return *this; + info.debug_message_type = type; + return *this; } InstanceBuilder& InstanceBuilder::add_debug_messenger_type(VkDebugUtilsMessageTypeFlagsEXT type) { - info.debug_message_type = info.debug_message_type | type; - return *this; + info.debug_message_type = info.debug_message_type | type; + return *this; } InstanceBuilder& InstanceBuilder::add_validation_disable(VkValidationCheckEXT check) { - info.disabled_validation_checks.push_back(check); - return *this; + info.disabled_validation_checks.push_back(check); + return *this; } InstanceBuilder& InstanceBuilder::add_validation_feature_enable(VkValidationFeatureEnableEXT enable) { - info.enabled_validation_features.push_back(enable); - return *this; + info.enabled_validation_features.push_back(enable); + return *this; } InstanceBuilder& InstanceBuilder::add_validation_feature_disable(VkValidationFeatureDisableEXT disable) { - info.disabled_validation_features.push_back(disable); - return *this; + info.disabled_validation_features.push_back(disable); + return *this; } InstanceBuilder& InstanceBuilder::set_allocation_callbacks(VkAllocationCallbacks* callbacks) { - info.allocation_callbacks = callbacks; - return *this; + info.allocation_callbacks = callbacks; + return *this; } void destroy_debug_messenger(VkInstance const instance, VkDebugUtilsMessengerEXT const messenger); @@ -855,16 +855,16 @@ namespace detail { std::vector check_device_extension_support( std::vector const& available_extensions, std::vector const& desired_extensions) { - std::vector extensions_to_enable; - for (const auto& avail_ext : available_extensions) { - for (auto& req_ext : desired_extensions) { - if (avail_ext == req_ext) { - extensions_to_enable.push_back(req_ext); - break; - } - } - } - return extensions_to_enable; + std::vector extensions_to_enable; + for (const auto& avail_ext : available_extensions) { + for (auto& req_ext : desired_extensions) { + if (avail_ext == req_ext) { + extensions_to_enable.push_back(req_ext); + break; + } + } + } + return extensions_to_enable; } // clang-format off @@ -938,438 +938,438 @@ bool supports_features(VkPhysicalDeviceFeatures supported, // clang-format on // Finds the first queue which supports the desired operations. Returns QUEUE_INDEX_MAX_VALUE if none is found uint32_t get_first_queue_index(std::vector const& families, VkQueueFlags desired_flags) { - for (uint32_t i = 0; i < static_cast(families.size()); i++) { - if ((families[i].queueFlags & desired_flags) == desired_flags) return i; - } - return QUEUE_INDEX_MAX_VALUE; + for (uint32_t i = 0; i < static_cast(families.size()); i++) { + if ((families[i].queueFlags & desired_flags) == desired_flags) return i; + } + return QUEUE_INDEX_MAX_VALUE; } // Finds the queue which is separate from the graphics queue and has the desired flag and not the // undesired flag, but will select it if no better options are available compute support. Returns // QUEUE_INDEX_MAX_VALUE if none is found. uint32_t get_separate_queue_index( std::vector const& families, VkQueueFlags desired_flags, VkQueueFlags undesired_flags) { - uint32_t index = QUEUE_INDEX_MAX_VALUE; - for (uint32_t i = 0; i < static_cast(families.size()); i++) { - if ((families[i].queueFlags & desired_flags) == desired_flags && ((families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)) { - if ((families[i].queueFlags & undesired_flags) == 0) { - return i; - } else { - index = i; - } - } - } - return index; + uint32_t index = QUEUE_INDEX_MAX_VALUE; + for (uint32_t i = 0; i < static_cast(families.size()); i++) { + if ((families[i].queueFlags & desired_flags) == desired_flags && ((families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)) { + if ((families[i].queueFlags & undesired_flags) == 0) { + return i; + } else { + index = i; + } + } + } + return index; } // finds the first queue which supports only the desired flag (not graphics or transfer). Returns QUEUE_INDEX_MAX_VALUE if none is found. uint32_t get_dedicated_queue_index( std::vector const& families, VkQueueFlags desired_flags, VkQueueFlags undesired_flags) { - for (uint32_t i = 0; i < static_cast(families.size()); i++) { - if ((families[i].queueFlags & desired_flags) == desired_flags && - (families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0 && (families[i].queueFlags & undesired_flags) == 0) - return i; - } - return QUEUE_INDEX_MAX_VALUE; + for (uint32_t i = 0; i < static_cast(families.size()); i++) { + if ((families[i].queueFlags & desired_flags) == desired_flags && + (families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0 && (families[i].queueFlags & undesired_flags) == 0) + return i; + } + return QUEUE_INDEX_MAX_VALUE; } // finds the first queue which supports presenting. returns QUEUE_INDEX_MAX_VALUE if none is found uint32_t get_present_queue_index( VkPhysicalDevice const phys_device, VkSurfaceKHR const surface, std::vector const& families) { - for (uint32_t i = 0; i < static_cast(families.size()); i++) { - VkBool32 presentSupport = false; - if (surface != VK_NULL_HANDLE) { - VkResult res = detail::vulkan_functions().fp_vkGetPhysicalDeviceSurfaceSupportKHR(phys_device, i, surface, &presentSupport); - if (res != VK_SUCCESS) return QUEUE_INDEX_MAX_VALUE; // TODO: determine if this should fail another way - } - if (presentSupport == VK_TRUE) return i; - } - return QUEUE_INDEX_MAX_VALUE; + for (uint32_t i = 0; i < static_cast(families.size()); i++) { + VkBool32 presentSupport = false; + if (surface != VK_NULL_HANDLE) { + VkResult res = detail::vulkan_functions().fp_vkGetPhysicalDeviceSurfaceSupportKHR(phys_device, i, surface, &presentSupport); + if (res != VK_SUCCESS) return QUEUE_INDEX_MAX_VALUE; // TODO: determine if this should fail another way + } + if (presentSupport == VK_TRUE) return i; + } + return QUEUE_INDEX_MAX_VALUE; } } // namespace detail PhysicalDevice PhysicalDeviceSelector::populate_device_details(VkPhysicalDevice vk_phys_device, std::vector const& src_extended_features_chain) const { - PhysicalDevice physical_device{}; - physical_device.physical_device = vk_phys_device; - physical_device.surface = instance_info.surface; - physical_device.defer_surface_initialization = criteria.defer_surface_initialization; - physical_device.instance_version = instance_info.version; - auto queue_families = detail::get_vector_noerror( - detail::vulkan_functions().fp_vkGetPhysicalDeviceQueueFamilyProperties, vk_phys_device); - physical_device.queue_families = queue_families; + PhysicalDevice physical_device{}; + physical_device.physical_device = vk_phys_device; + physical_device.surface = instance_info.surface; + physical_device.defer_surface_initialization = criteria.defer_surface_initialization; + physical_device.instance_version = instance_info.version; + auto queue_families = detail::get_vector_noerror( + detail::vulkan_functions().fp_vkGetPhysicalDeviceQueueFamilyProperties, vk_phys_device); + physical_device.queue_families = queue_families; - detail::vulkan_functions().fp_vkGetPhysicalDeviceProperties(vk_phys_device, &physical_device.properties); - detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures(vk_phys_device, &physical_device.features); - detail::vulkan_functions().fp_vkGetPhysicalDeviceMemoryProperties(vk_phys_device, &physical_device.memory_properties); + detail::vulkan_functions().fp_vkGetPhysicalDeviceProperties(vk_phys_device, &physical_device.properties); + detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures(vk_phys_device, &physical_device.features); + detail::vulkan_functions().fp_vkGetPhysicalDeviceMemoryProperties(vk_phys_device, &physical_device.memory_properties); - physical_device.name = physical_device.properties.deviceName; + physical_device.name = physical_device.properties.deviceName; - std::vector available_extensions; - auto available_extensions_ret = detail::get_vector( - available_extensions, detail::vulkan_functions().fp_vkEnumerateDeviceExtensionProperties, vk_phys_device, nullptr); - if (available_extensions_ret != VK_SUCCESS) return physical_device; - for (const auto& ext : available_extensions) { - physical_device.extensions.push_back(&ext.extensionName[0]); - } + std::vector available_extensions; + auto available_extensions_ret = detail::get_vector( + available_extensions, detail::vulkan_functions().fp_vkEnumerateDeviceExtensionProperties, vk_phys_device, nullptr); + if (available_extensions_ret != VK_SUCCESS) return physical_device; + for (const auto& ext : available_extensions) { + physical_device.extensions.push_back(&ext.extensionName[0]); + } - physical_device.features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; // same value as the non-KHR version - physical_device.properties2_ext_enabled = instance_info.properties2_ext_enabled; + physical_device.features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; // same value as the non-KHR version + physical_device.properties2_ext_enabled = instance_info.properties2_ext_enabled; - auto fill_chain = src_extended_features_chain; + auto fill_chain = src_extended_features_chain; - bool instance_is_1_1 = instance_info.version >= VKB_VK_API_VERSION_1_1; - if (!fill_chain.empty() && (instance_is_1_1 || instance_info.properties2_ext_enabled)) { + bool instance_is_1_1 = instance_info.version >= VKB_VK_API_VERSION_1_1; + if (!fill_chain.empty() && (instance_is_1_1 || instance_info.properties2_ext_enabled)) { - detail::GenericFeaturesPNextNode* prev = nullptr; - for (auto& extension : fill_chain) { - if (prev != nullptr) { - prev->pNext = &extension; - } - prev = &extension; - } + detail::GenericFeaturesPNextNode* prev = nullptr; + for (auto& extension : fill_chain) { + if (prev != nullptr) { + prev->pNext = &extension; + } + prev = &extension; + } - VkPhysicalDeviceFeatures2 local_features{}; - local_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; // KHR is same as core here - local_features.pNext = &fill_chain.front(); - // Use KHR function if not able to use the core function - if (instance_is_1_1) { - detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2(vk_phys_device, &local_features); - } else { - detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2KHR(vk_phys_device, &local_features); - } - physical_device.extended_features_chain = fill_chain; - } + VkPhysicalDeviceFeatures2 local_features{}; + local_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; // KHR is same as core here + local_features.pNext = &fill_chain.front(); + // Use KHR function if not able to use the core function + if (instance_is_1_1) { + detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2(vk_phys_device, &local_features); + } else { + detail::vulkan_functions().fp_vkGetPhysicalDeviceFeatures2KHR(vk_phys_device, &local_features); + } + physical_device.extended_features_chain = fill_chain; + } - return physical_device; + return physical_device; } PhysicalDevice::Suitable PhysicalDeviceSelector::is_device_suitable(PhysicalDevice const& pd) const { - PhysicalDevice::Suitable suitable = PhysicalDevice::Suitable::yes; + PhysicalDevice::Suitable suitable = PhysicalDevice::Suitable::yes; - if (criteria.name.size() > 0 && criteria.name != pd.properties.deviceName) return PhysicalDevice::Suitable::no; + if (criteria.name.size() > 0 && criteria.name != pd.properties.deviceName) return PhysicalDevice::Suitable::no; - if (criteria.required_version > pd.properties.apiVersion) return PhysicalDevice::Suitable::no; - if (criteria.desired_version > pd.properties.apiVersion) suitable = PhysicalDevice::Suitable::partial; + if (criteria.required_version > pd.properties.apiVersion) return PhysicalDevice::Suitable::no; + if (criteria.desired_version > pd.properties.apiVersion) suitable = PhysicalDevice::Suitable::partial; - bool dedicated_compute = detail::get_dedicated_queue_index(pd.queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT) != - detail::QUEUE_INDEX_MAX_VALUE; - bool dedicated_transfer = detail::get_dedicated_queue_index(pd.queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT) != - detail::QUEUE_INDEX_MAX_VALUE; - bool separate_compute = detail::get_separate_queue_index(pd.queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT) != - detail::QUEUE_INDEX_MAX_VALUE; - bool separate_transfer = detail::get_separate_queue_index(pd.queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT) != - detail::QUEUE_INDEX_MAX_VALUE; + bool dedicated_compute = detail::get_dedicated_queue_index(pd.queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT) != + detail::QUEUE_INDEX_MAX_VALUE; + bool dedicated_transfer = detail::get_dedicated_queue_index(pd.queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT) != + detail::QUEUE_INDEX_MAX_VALUE; + bool separate_compute = detail::get_separate_queue_index(pd.queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT) != + detail::QUEUE_INDEX_MAX_VALUE; + bool separate_transfer = detail::get_separate_queue_index(pd.queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT) != + detail::QUEUE_INDEX_MAX_VALUE; - bool present_queue = detail::get_present_queue_index(pd.physical_device, instance_info.surface, pd.queue_families) != - detail::QUEUE_INDEX_MAX_VALUE; + bool present_queue = detail::get_present_queue_index(pd.physical_device, instance_info.surface, pd.queue_families) != + detail::QUEUE_INDEX_MAX_VALUE; - if (criteria.require_dedicated_compute_queue && !dedicated_compute) return PhysicalDevice::Suitable::no; - if (criteria.require_dedicated_transfer_queue && !dedicated_transfer) return PhysicalDevice::Suitable::no; - if (criteria.require_separate_compute_queue && !separate_compute) return PhysicalDevice::Suitable::no; - if (criteria.require_separate_transfer_queue && !separate_transfer) return PhysicalDevice::Suitable::no; - if (criteria.require_present && !present_queue && !criteria.defer_surface_initialization) - return PhysicalDevice::Suitable::no; + if (criteria.require_dedicated_compute_queue && !dedicated_compute) return PhysicalDevice::Suitable::no; + if (criteria.require_dedicated_transfer_queue && !dedicated_transfer) return PhysicalDevice::Suitable::no; + if (criteria.require_separate_compute_queue && !separate_compute) return PhysicalDevice::Suitable::no; + if (criteria.require_separate_transfer_queue && !separate_transfer) return PhysicalDevice::Suitable::no; + if (criteria.require_present && !present_queue && !criteria.defer_surface_initialization) + return PhysicalDevice::Suitable::no; - auto required_extensions_supported = detail::check_device_extension_support(pd.extensions, criteria.required_extensions); - if (required_extensions_supported.size() != criteria.required_extensions.size()) - return PhysicalDevice::Suitable::no; + auto required_extensions_supported = detail::check_device_extension_support(pd.extensions, criteria.required_extensions); + if (required_extensions_supported.size() != criteria.required_extensions.size()) + return PhysicalDevice::Suitable::no; - auto desired_extensions_supported = detail::check_device_extension_support(pd.extensions, criteria.desired_extensions); - if (desired_extensions_supported.size() != criteria.desired_extensions.size()) - suitable = PhysicalDevice::Suitable::partial; + auto desired_extensions_supported = detail::check_device_extension_support(pd.extensions, criteria.desired_extensions); + if (desired_extensions_supported.size() != criteria.desired_extensions.size()) + suitable = PhysicalDevice::Suitable::partial; - if (!criteria.defer_surface_initialization && criteria.require_present) { - std::vector formats; - std::vector present_modes; + if (!criteria.defer_surface_initialization && criteria.require_present) { + std::vector formats; + std::vector present_modes; - auto formats_ret = detail::get_vector(formats, - detail::vulkan_functions().fp_vkGetPhysicalDeviceSurfaceFormatsKHR, - pd.physical_device, - instance_info.surface); - auto present_modes_ret = detail::get_vector(present_modes, - detail::vulkan_functions().fp_vkGetPhysicalDeviceSurfacePresentModesKHR, - pd.physical_device, - instance_info.surface); + auto formats_ret = detail::get_vector(formats, + detail::vulkan_functions().fp_vkGetPhysicalDeviceSurfaceFormatsKHR, + pd.physical_device, + instance_info.surface); + auto present_modes_ret = detail::get_vector(present_modes, + detail::vulkan_functions().fp_vkGetPhysicalDeviceSurfacePresentModesKHR, + pd.physical_device, + instance_info.surface); - if (formats_ret != VK_SUCCESS || present_modes_ret != VK_SUCCESS || formats.empty() || present_modes.empty()) { - return PhysicalDevice::Suitable::no; - } - } + if (formats_ret != VK_SUCCESS || present_modes_ret != VK_SUCCESS || formats.empty() || present_modes.empty()) { + return PhysicalDevice::Suitable::no; + } + } - if (!criteria.allow_any_type && pd.properties.deviceType != static_cast(criteria.preferred_type)) { - suitable = PhysicalDevice::Suitable::partial; - } + if (!criteria.allow_any_type && pd.properties.deviceType != static_cast(criteria.preferred_type)) { + suitable = PhysicalDevice::Suitable::partial; + } - bool required_features_supported = detail::supports_features( - pd.features, criteria.required_features, pd.extended_features_chain, criteria.extended_features_chain); - if (!required_features_supported) return PhysicalDevice::Suitable::no; + bool required_features_supported = detail::supports_features( + pd.features, criteria.required_features, pd.extended_features_chain, criteria.extended_features_chain); + if (!required_features_supported) return PhysicalDevice::Suitable::no; - for (uint32_t i = 0; i < pd.memory_properties.memoryHeapCount; i++) { - if (pd.memory_properties.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) { - if (pd.memory_properties.memoryHeaps[i].size < criteria.required_mem_size) { - return PhysicalDevice::Suitable::no; - } else if (pd.memory_properties.memoryHeaps[i].size < criteria.desired_mem_size) { - suitable = PhysicalDevice::Suitable::partial; - } - } - } + for (uint32_t i = 0; i < pd.memory_properties.memoryHeapCount; i++) { + if (pd.memory_properties.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) { + if (pd.memory_properties.memoryHeaps[i].size < criteria.required_mem_size) { + return PhysicalDevice::Suitable::no; + } else if (pd.memory_properties.memoryHeaps[i].size < criteria.desired_mem_size) { + suitable = PhysicalDevice::Suitable::partial; + } + } + } - return suitable; + return suitable; } // delegate construction to the one with an explicit surface parameter PhysicalDeviceSelector::PhysicalDeviceSelector(Instance const& instance) : PhysicalDeviceSelector(instance, VK_NULL_HANDLE) {} PhysicalDeviceSelector::PhysicalDeviceSelector(Instance const& instance, VkSurfaceKHR surface) { - instance_info.instance = instance.instance; - instance_info.version = instance.instance_version; - instance_info.properties2_ext_enabled = instance.properties2_ext_enabled; - instance_info.surface = surface; - criteria.require_present = !instance.headless; - criteria.required_version = instance.api_version; - criteria.desired_version = instance.api_version; + instance_info.instance = instance.instance; + instance_info.version = instance.instance_version; + instance_info.properties2_ext_enabled = instance.properties2_ext_enabled; + instance_info.surface = surface; + criteria.require_present = !instance.headless; + criteria.required_version = instance.api_version; + criteria.desired_version = instance.api_version; } Result> PhysicalDeviceSelector::select_impl(DeviceSelectionMode selection) const { #if !defined(NDEBUG) - // Validation - for (const auto& node : criteria.extended_features_chain) { - assert(node.sType != static_cast(0) && - "Features struct sType must be filled with the struct's " - "corresponding VkStructureType enum"); - assert(node.sType != VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 && - "Do not pass VkPhysicalDeviceFeatures2 as a required extension feature structure. An " - "instance of this is managed internally for selection criteria and device creation."); - } + // Validation + for (const auto& node : criteria.extended_features_chain) { + assert(node.sType != static_cast(0) && + "Features struct sType must be filled with the struct's " + "corresponding VkStructureType enum"); + assert(node.sType != VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 && + "Do not pass VkPhysicalDeviceFeatures2 as a required extension feature structure. An " + "instance of this is managed internally for selection criteria and device creation."); + } #endif - if (criteria.require_present && !criteria.defer_surface_initialization) { - if (instance_info.surface == VK_NULL_HANDLE) - return Result>{ PhysicalDeviceError::no_surface_provided }; - } + if (criteria.require_present && !criteria.defer_surface_initialization) { + if (instance_info.surface == VK_NULL_HANDLE) + return Result>{ PhysicalDeviceError::no_surface_provided }; + } - // Get the VkPhysicalDevice handles on the system - std::vector vk_physical_devices; + // Get the VkPhysicalDevice handles on the system + std::vector vk_physical_devices; - auto vk_physical_devices_ret = detail::get_vector( - vk_physical_devices, detail::vulkan_functions().fp_vkEnumeratePhysicalDevices, instance_info.instance); - if (vk_physical_devices_ret != VK_SUCCESS) { - return Result>{ PhysicalDeviceError::failed_enumerate_physical_devices, vk_physical_devices_ret }; - } - if (vk_physical_devices.size() == 0) { - return Result>{ PhysicalDeviceError::no_physical_devices_found }; - } + auto vk_physical_devices_ret = detail::get_vector( + vk_physical_devices, detail::vulkan_functions().fp_vkEnumeratePhysicalDevices, instance_info.instance); + if (vk_physical_devices_ret != VK_SUCCESS) { + return Result>{ PhysicalDeviceError::failed_enumerate_physical_devices, vk_physical_devices_ret }; + } + if (vk_physical_devices.size() == 0) { + return Result>{ PhysicalDeviceError::no_physical_devices_found }; + } - auto fill_out_phys_dev_with_criteria = [&](PhysicalDevice& phys_dev) { - phys_dev.features = criteria.required_features; - phys_dev.extended_features_chain = criteria.extended_features_chain; - bool portability_ext_available = false; - for (const auto& ext : phys_dev.extensions) - if (criteria.enable_portability_subset && ext == "VK_KHR_portability_subset") - portability_ext_available = true; + auto fill_out_phys_dev_with_criteria = [&](PhysicalDevice& phys_dev) { + phys_dev.features = criteria.required_features; + phys_dev.extended_features_chain = criteria.extended_features_chain; + bool portability_ext_available = false; + for (const auto& ext : phys_dev.extensions) + if (criteria.enable_portability_subset && ext == "VK_KHR_portability_subset") + portability_ext_available = true; - auto desired_extensions_supported = detail::check_device_extension_support(phys_dev.extensions, criteria.desired_extensions); + auto desired_extensions_supported = detail::check_device_extension_support(phys_dev.extensions, criteria.desired_extensions); - phys_dev.extensions.clear(); - phys_dev.extensions.insert( - phys_dev.extensions.end(), criteria.required_extensions.begin(), criteria.required_extensions.end()); - phys_dev.extensions.insert( - phys_dev.extensions.end(), desired_extensions_supported.begin(), desired_extensions_supported.end()); - if (portability_ext_available) { - phys_dev.extensions.push_back("VK_KHR_portability_subset"); - } - }; + phys_dev.extensions.clear(); + phys_dev.extensions.insert( + phys_dev.extensions.end(), criteria.required_extensions.begin(), criteria.required_extensions.end()); + phys_dev.extensions.insert( + phys_dev.extensions.end(), desired_extensions_supported.begin(), desired_extensions_supported.end()); + if (portability_ext_available) { + phys_dev.extensions.push_back("VK_KHR_portability_subset"); + } + }; - // if this option is set, always return only the first physical device found - if (criteria.use_first_gpu_unconditionally && vk_physical_devices.size() > 0) { - PhysicalDevice physical_device = populate_device_details(vk_physical_devices[0], criteria.extended_features_chain); - fill_out_phys_dev_with_criteria(physical_device); - return std::vector{ physical_device }; - } + // if this option is set, always return only the first physical device found + if (criteria.use_first_gpu_unconditionally && vk_physical_devices.size() > 0) { + PhysicalDevice physical_device = populate_device_details(vk_physical_devices[0], criteria.extended_features_chain); + fill_out_phys_dev_with_criteria(physical_device); + return std::vector{ physical_device }; + } - // Populate their details and check their suitability - std::vector physical_devices; - for (auto& vk_physical_device : vk_physical_devices) { - PhysicalDevice phys_dev = populate_device_details(vk_physical_device, criteria.extended_features_chain); - phys_dev.suitable = is_device_suitable(phys_dev); - if (phys_dev.suitable != PhysicalDevice::Suitable::no) { - physical_devices.push_back(phys_dev); - } - } + // Populate their details and check their suitability + std::vector physical_devices; + for (auto& vk_physical_device : vk_physical_devices) { + PhysicalDevice phys_dev = populate_device_details(vk_physical_device, criteria.extended_features_chain); + phys_dev.suitable = is_device_suitable(phys_dev); + if (phys_dev.suitable != PhysicalDevice::Suitable::no) { + physical_devices.push_back(phys_dev); + } + } - // sort the list into fully and partially suitable devices. use stable_partition to maintain relative order - const auto partition_index = std::stable_partition(physical_devices.begin(), physical_devices.end(), [](auto const& pd) { - return pd.suitable == PhysicalDevice::Suitable::yes; - }); + // sort the list into fully and partially suitable devices. use stable_partition to maintain relative order + const auto partition_index = std::stable_partition(physical_devices.begin(), physical_devices.end(), [](auto const& pd) { + return pd.suitable == PhysicalDevice::Suitable::yes; + }); - // Remove the partially suitable elements if they aren't desired - if (selection == DeviceSelectionMode::only_fully_suitable) { - physical_devices.erase(partition_index, physical_devices.end()); - } + // Remove the partially suitable elements if they aren't desired + if (selection == DeviceSelectionMode::only_fully_suitable) { + physical_devices.erase(partition_index, physical_devices.end()); + } - // Make the physical device ready to be used to create a Device from it - for (auto& physical_device : physical_devices) { - fill_out_phys_dev_with_criteria(physical_device); - } + // Make the physical device ready to be used to create a Device from it + for (auto& physical_device : physical_devices) { + fill_out_phys_dev_with_criteria(physical_device); + } - return physical_devices; + return physical_devices; } Result PhysicalDeviceSelector::select(DeviceSelectionMode selection) const { - auto const selected_devices = select_impl(selection); + auto const selected_devices = select_impl(selection); - if (!selected_devices) return Result{ selected_devices.error() }; - if (selected_devices.value().size() == 0) { - return Result{ PhysicalDeviceError::no_suitable_device }; - } + if (!selected_devices) return Result{ selected_devices.error() }; + if (selected_devices.value().size() == 0) { + return Result{ PhysicalDeviceError::no_suitable_device }; + } - return selected_devices.value().at(0); + return selected_devices.value().at(0); } // Return all devices which are considered suitable - intended for applications which want to let the user pick the physical device Result> PhysicalDeviceSelector::select_devices(DeviceSelectionMode selection) const { - auto const selected_devices = select_impl(selection); - if (!selected_devices) return Result>{ selected_devices.error() }; - if (selected_devices.value().size() == 0) { - return Result>{ PhysicalDeviceError::no_suitable_device }; - } - return selected_devices.value(); + auto const selected_devices = select_impl(selection); + if (!selected_devices) return Result>{ selected_devices.error() }; + if (selected_devices.value().size() == 0) { + return Result>{ PhysicalDeviceError::no_suitable_device }; + } + return selected_devices.value(); } Result> PhysicalDeviceSelector::select_device_names(DeviceSelectionMode selection) const { - auto const selected_devices = select_impl(selection); - if (!selected_devices) return Result>{ selected_devices.error() }; - if (selected_devices.value().size() == 0) { - return Result>{ PhysicalDeviceError::no_suitable_device }; - } - std::vector names; - for (const auto& pd : selected_devices.value()) { - names.push_back(pd.name); - } - return names; + auto const selected_devices = select_impl(selection); + if (!selected_devices) return Result>{ selected_devices.error() }; + if (selected_devices.value().size() == 0) { + return Result>{ PhysicalDeviceError::no_suitable_device }; + } + std::vector names; + for (const auto& pd : selected_devices.value()) { + names.push_back(pd.name); + } + return names; } PhysicalDeviceSelector& PhysicalDeviceSelector::set_surface(VkSurfaceKHR surface) { - instance_info.surface = surface; - return *this; + instance_info.surface = surface; + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::set_name(std::string const& name) { - criteria.name = name; - return *this; + criteria.name = name; + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::prefer_gpu_device_type(PreferredDeviceType type) { - criteria.preferred_type = type; - return *this; + criteria.preferred_type = type; + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::allow_any_gpu_device_type(bool allow_any_type) { - criteria.allow_any_type = allow_any_type; - return *this; + criteria.allow_any_type = allow_any_type; + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::require_present(bool require) { - criteria.require_present = require; - return *this; + criteria.require_present = require; + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::require_dedicated_transfer_queue() { - criteria.require_dedicated_transfer_queue = true; - return *this; + criteria.require_dedicated_transfer_queue = true; + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::require_dedicated_compute_queue() { - criteria.require_dedicated_compute_queue = true; - return *this; + criteria.require_dedicated_compute_queue = true; + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::require_separate_transfer_queue() { - criteria.require_separate_transfer_queue = true; - return *this; + criteria.require_separate_transfer_queue = true; + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::require_separate_compute_queue() { - criteria.require_separate_compute_queue = true; - return *this; + criteria.require_separate_compute_queue = true; + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::required_device_memory_size(VkDeviceSize size) { - criteria.required_mem_size = size; - return *this; + criteria.required_mem_size = size; + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::desired_device_memory_size(VkDeviceSize size) { - criteria.desired_mem_size = size; - return *this; + criteria.desired_mem_size = size; + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::add_required_extension(const char* extension) { - criteria.required_extensions.push_back(extension); - return *this; + criteria.required_extensions.push_back(extension); + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::add_required_extensions(std::vector extensions) { - for (const auto& ext : extensions) { - criteria.required_extensions.push_back(ext); - } - return *this; + for (const auto& ext : extensions) { + criteria.required_extensions.push_back(ext); + } + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::add_desired_extension(const char* extension) { - criteria.desired_extensions.push_back(extension); - return *this; + criteria.desired_extensions.push_back(extension); + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::add_desired_extensions(std::vector extensions) { - for (const auto& ext : extensions) { - criteria.desired_extensions.push_back(ext); - } - return *this; + for (const auto& ext : extensions) { + criteria.desired_extensions.push_back(ext); + } + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::set_minimum_version(uint32_t major, uint32_t minor) { - criteria.required_version = VKB_MAKE_VK_VERSION(0, major, minor, 0); - return *this; + criteria.required_version = VKB_MAKE_VK_VERSION(0, major, minor, 0); + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::set_desired_version(uint32_t major, uint32_t minor) { - criteria.desired_version = VKB_MAKE_VK_VERSION(0, major, minor, 0); - return *this; + criteria.desired_version = VKB_MAKE_VK_VERSION(0, major, minor, 0); + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::disable_portability_subset() { - criteria.enable_portability_subset = false; - return *this; + criteria.enable_portability_subset = false; + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::set_required_features(VkPhysicalDeviceFeatures const& features) { - criteria.required_features = features; - return *this; + criteria.required_features = features; + return *this; } #if defined(VKB_VK_API_VERSION_1_2) // Just calls add_required_features PhysicalDeviceSelector& PhysicalDeviceSelector::set_required_features_11(VkPhysicalDeviceVulkan11Features features_11) { - features_11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; - add_required_extension_features(features_11); - return *this; + features_11.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; + add_required_extension_features(features_11); + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::set_required_features_12(VkPhysicalDeviceVulkan12Features features_12) { - features_12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; - add_required_extension_features(features_12); - return *this; + features_12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; + add_required_extension_features(features_12); + return *this; } #endif #if defined(VKB_VK_API_VERSION_1_3) PhysicalDeviceSelector& PhysicalDeviceSelector::set_required_features_13(VkPhysicalDeviceVulkan13Features features_13) { - features_13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; - add_required_extension_features(features_13); - return *this; + features_13.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES; + add_required_extension_features(features_13); + return *this; } #endif PhysicalDeviceSelector& PhysicalDeviceSelector::defer_surface_initialization() { - criteria.defer_surface_initialization = true; - return *this; + criteria.defer_surface_initialization = true; + return *this; } PhysicalDeviceSelector& PhysicalDeviceSelector::select_first_device_unconditionally(bool unconditionally) { - criteria.use_first_gpu_unconditionally = unconditionally; - return *this; + criteria.use_first_gpu_unconditionally = unconditionally; + return *this; } // PhysicalDevice bool PhysicalDevice::has_dedicated_compute_queue() const { - return detail::get_dedicated_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT) != detail::QUEUE_INDEX_MAX_VALUE; + return detail::get_dedicated_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT) != detail::QUEUE_INDEX_MAX_VALUE; } bool PhysicalDevice::has_separate_compute_queue() const { - return detail::get_separate_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT) != detail::QUEUE_INDEX_MAX_VALUE; + return detail::get_separate_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT) != detail::QUEUE_INDEX_MAX_VALUE; } bool PhysicalDevice::has_dedicated_transfer_queue() const { - return detail::get_dedicated_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT) != detail::QUEUE_INDEX_MAX_VALUE; + return detail::get_dedicated_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT) != detail::QUEUE_INDEX_MAX_VALUE; } bool PhysicalDevice::has_separate_transfer_queue() const { - return detail::get_separate_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT) != detail::QUEUE_INDEX_MAX_VALUE; + return detail::get_separate_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT) != detail::QUEUE_INDEX_MAX_VALUE; } std::vector PhysicalDevice::get_queue_families() const { return queue_families; } std::vector PhysicalDevice::get_extensions() const { return extensions; } @@ -1378,59 +1378,59 @@ PhysicalDevice::operator VkPhysicalDevice() const { return this->physical_device // ---- Queues ---- // Result Device::get_queue_index(QueueType type) const { - uint32_t index = detail::QUEUE_INDEX_MAX_VALUE; - switch (type) { - case QueueType::present: - index = detail::get_present_queue_index(physical_device.physical_device, surface, queue_families); - if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result{ QueueError::present_unavailable }; - break; - case QueueType::graphics: - index = detail::get_first_queue_index(queue_families, VK_QUEUE_GRAPHICS_BIT); - if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result{ QueueError::graphics_unavailable }; - break; - case QueueType::compute: - index = detail::get_separate_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT); - if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result{ QueueError::compute_unavailable }; - break; - case QueueType::transfer: - index = detail::get_separate_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT); - if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result{ QueueError::transfer_unavailable }; - break; - default: - return Result{ QueueError::invalid_queue_family_index }; - } - return index; + uint32_t index = detail::QUEUE_INDEX_MAX_VALUE; + switch (type) { + case QueueType::present: + index = detail::get_present_queue_index(physical_device.physical_device, surface, queue_families); + if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result{ QueueError::present_unavailable }; + break; + case QueueType::graphics: + index = detail::get_first_queue_index(queue_families, VK_QUEUE_GRAPHICS_BIT); + if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result{ QueueError::graphics_unavailable }; + break; + case QueueType::compute: + index = detail::get_separate_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT); + if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result{ QueueError::compute_unavailable }; + break; + case QueueType::transfer: + index = detail::get_separate_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT); + if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result{ QueueError::transfer_unavailable }; + break; + default: + return Result{ QueueError::invalid_queue_family_index }; + } + return index; } Result Device::get_dedicated_queue_index(QueueType type) const { - uint32_t index = detail::QUEUE_INDEX_MAX_VALUE; - switch (type) { - case QueueType::compute: - index = detail::get_dedicated_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT); - if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result{ QueueError::compute_unavailable }; - break; - case QueueType::transfer: - index = detail::get_dedicated_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT); - if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result{ QueueError::transfer_unavailable }; - break; - default: - return Result{ QueueError::invalid_queue_family_index }; - } - return index; + uint32_t index = detail::QUEUE_INDEX_MAX_VALUE; + switch (type) { + case QueueType::compute: + index = detail::get_dedicated_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT); + if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result{ QueueError::compute_unavailable }; + break; + case QueueType::transfer: + index = detail::get_dedicated_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT); + if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result{ QueueError::transfer_unavailable }; + break; + default: + return Result{ QueueError::invalid_queue_family_index }; + } + return index; } Result Device::get_queue(QueueType type) const { - auto index = get_queue_index(type); - if (!index.has_value()) return { index.error() }; - VkQueue out_queue; - internal_table.fp_vkGetDeviceQueue(device, index.value(), 0, &out_queue); - return out_queue; + auto index = get_queue_index(type); + if (!index.has_value()) return { index.error() }; + VkQueue out_queue; + internal_table.fp_vkGetDeviceQueue(device, index.value(), 0, &out_queue); + return out_queue; } Result Device::get_dedicated_queue(QueueType type) const { - auto index = get_dedicated_queue_index(type); - if (!index.has_value()) return { index.error() }; - VkQueue out_queue; - internal_table.fp_vkGetDeviceQueue(device, index.value(), 0, &out_queue); - return out_queue; + auto index = get_dedicated_queue_index(type); + if (!index.has_value()) return { index.error() }; + VkQueue out_queue; + internal_table.fp_vkGetDeviceQueue(device, index.value(), 0, &out_queue); + return out_queue; } // ---- Dispatch ---- // @@ -1443,562 +1443,562 @@ Device::operator VkDevice() const { return this->device; } CustomQueueDescription::CustomQueueDescription(uint32_t index, uint32_t count, std::vector priorities) : index(index), count(count), priorities(priorities) { - assert(count == priorities.size()); + assert(count == priorities.size()); } void destroy_device(Device device) { - device.internal_table.fp_vkDestroyDevice(device.device, device.allocation_callbacks); + device.internal_table.fp_vkDestroyDevice(device.device, device.allocation_callbacks); } DeviceBuilder::DeviceBuilder(PhysicalDevice phys_device) { physical_device = phys_device; } Result DeviceBuilder::build() const { - std::vector queue_descriptions; - queue_descriptions.insert(queue_descriptions.end(), info.queue_descriptions.begin(), info.queue_descriptions.end()); + std::vector queue_descriptions; + queue_descriptions.insert(queue_descriptions.end(), info.queue_descriptions.begin(), info.queue_descriptions.end()); - if (queue_descriptions.size() == 0) { - for (uint32_t i = 0; i < physical_device.queue_families.size(); i++) { - queue_descriptions.push_back(CustomQueueDescription{ i, 1, std::vector{ 1.0f } }); - } - } + if (queue_descriptions.size() == 0) { + for (uint32_t i = 0; i < physical_device.queue_families.size(); i++) { + queue_descriptions.push_back(CustomQueueDescription{ i, 1, std::vector{ 1.0f } }); + } + } - std::vector queueCreateInfos; - for (auto& desc : queue_descriptions) { - VkDeviceQueueCreateInfo queue_create_info = {}; - queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_create_info.queueFamilyIndex = desc.index; - queue_create_info.queueCount = desc.count; - queue_create_info.pQueuePriorities = desc.priorities.data(); - queueCreateInfos.push_back(queue_create_info); - } + std::vector queueCreateInfos; + for (auto& desc : queue_descriptions) { + VkDeviceQueueCreateInfo queue_create_info = {}; + queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_create_info.queueFamilyIndex = desc.index; + queue_create_info.queueCount = desc.count; + queue_create_info.pQueuePriorities = desc.priorities.data(); + queueCreateInfos.push_back(queue_create_info); + } - std::vector extensions; - for (const auto& ext : physical_device.extensions) { - extensions.push_back(ext.c_str()); - } - if (physical_device.surface != VK_NULL_HANDLE || physical_device.defer_surface_initialization) - extensions.push_back({ VK_KHR_SWAPCHAIN_EXTENSION_NAME }); + std::vector extensions; + for (const auto& ext : physical_device.extensions) { + extensions.push_back(ext.c_str()); + } + if (physical_device.surface != VK_NULL_HANDLE || physical_device.defer_surface_initialization) + extensions.push_back({ VK_KHR_SWAPCHAIN_EXTENSION_NAME }); - std::vector final_pnext_chain; - VkDeviceCreateInfo device_create_info = {}; + std::vector final_pnext_chain; + VkDeviceCreateInfo device_create_info = {}; - bool user_defined_phys_dev_features_2 = false; - for (auto& pnext : info.pNext_chain) { - if (pnext->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2) { - user_defined_phys_dev_features_2 = true; - break; - } - } + bool user_defined_phys_dev_features_2 = false; + for (auto& pnext : info.pNext_chain) { + if (pnext->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2) { + user_defined_phys_dev_features_2 = true; + break; + } + } - if (user_defined_phys_dev_features_2 && physical_device.extended_features_chain.size() > 0) { - return { DeviceError::VkPhysicalDeviceFeatures2_in_pNext_chain_while_using_add_required_extension_features }; - } + if (user_defined_phys_dev_features_2 && physical_device.extended_features_chain.size() > 0) { + return { DeviceError::VkPhysicalDeviceFeatures2_in_pNext_chain_while_using_add_required_extension_features }; + } - // These objects must be alive during the call to vkCreateDevice - auto physical_device_extension_features_copy = physical_device.extended_features_chain; - VkPhysicalDeviceFeatures2 local_features2{}; - local_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + // These objects must be alive during the call to vkCreateDevice + auto physical_device_extension_features_copy = physical_device.extended_features_chain; + VkPhysicalDeviceFeatures2 local_features2{}; + local_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; - if (!user_defined_phys_dev_features_2) { - if (physical_device.instance_version >= VKB_VK_API_VERSION_1_1 || physical_device.properties2_ext_enabled) { - local_features2.features = physical_device.features; - final_pnext_chain.push_back(reinterpret_cast(&local_features2)); - for (auto& features_node : physical_device_extension_features_copy) { - final_pnext_chain.push_back(reinterpret_cast(&features_node)); - } - } else { - // Only set device_create_info.pEnabledFeatures when the pNext chain does not contain a VkPhysicalDeviceFeatures2 structure - device_create_info.pEnabledFeatures = &physical_device.features; - } - } + if (!user_defined_phys_dev_features_2) { + if (physical_device.instance_version >= VKB_VK_API_VERSION_1_1 || physical_device.properties2_ext_enabled) { + local_features2.features = physical_device.features; + final_pnext_chain.push_back(reinterpret_cast(&local_features2)); + for (auto& features_node : physical_device_extension_features_copy) { + final_pnext_chain.push_back(reinterpret_cast(&features_node)); + } + } else { + // Only set device_create_info.pEnabledFeatures when the pNext chain does not contain a VkPhysicalDeviceFeatures2 structure + device_create_info.pEnabledFeatures = &physical_device.features; + } + } - for (auto& pnext : info.pNext_chain) { - final_pnext_chain.push_back(pnext); - } + for (auto& pnext : info.pNext_chain) { + final_pnext_chain.push_back(pnext); + } - detail::setup_pNext_chain(device_create_info, final_pnext_chain); + detail::setup_pNext_chain(device_create_info, final_pnext_chain); #if !defined(NDEBUG) - for (auto& node : final_pnext_chain) { - assert(node->sType != VK_STRUCTURE_TYPE_APPLICATION_INFO); - } + for (auto& node : final_pnext_chain) { + assert(node->sType != VK_STRUCTURE_TYPE_APPLICATION_INFO); + } #endif - device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - device_create_info.flags = info.flags; - device_create_info.queueCreateInfoCount = static_cast(queueCreateInfos.size()); - device_create_info.pQueueCreateInfos = queueCreateInfos.data(); - device_create_info.enabledExtensionCount = static_cast(extensions.size()); - device_create_info.ppEnabledExtensionNames = extensions.data(); + device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + device_create_info.flags = info.flags; + device_create_info.queueCreateInfoCount = static_cast(queueCreateInfos.size()); + device_create_info.pQueueCreateInfos = queueCreateInfos.data(); + device_create_info.enabledExtensionCount = static_cast(extensions.size()); + device_create_info.ppEnabledExtensionNames = extensions.data(); - Device device; + 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 }; - } + 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; - device.allocation_callbacks = info.allocation_callbacks; - device.fp_vkGetDeviceProcAddr = detail::vulkan_functions().fp_vkGetDeviceProcAddr; - detail::vulkan_functions().get_device_proc_addr(device.device, device.internal_table.fp_vkGetDeviceQueue, "vkGetDeviceQueue"); - detail::vulkan_functions().get_device_proc_addr(device.device, device.internal_table.fp_vkDestroyDevice, "vkDestroyDevice"); - device.instance_version = physical_device.instance_version; - return device; + device.physical_device = physical_device; + device.surface = physical_device.surface; + device.queue_families = physical_device.queue_families; + device.allocation_callbacks = info.allocation_callbacks; + device.fp_vkGetDeviceProcAddr = detail::vulkan_functions().fp_vkGetDeviceProcAddr; + detail::vulkan_functions().get_device_proc_addr(device.device, device.internal_table.fp_vkGetDeviceQueue, "vkGetDeviceQueue"); + detail::vulkan_functions().get_device_proc_addr(device.device, device.internal_table.fp_vkDestroyDevice, "vkDestroyDevice"); + device.instance_version = physical_device.instance_version; + return device; } DeviceBuilder& DeviceBuilder::custom_queue_setup(std::vector queue_descriptions) { - info.queue_descriptions = queue_descriptions; - return *this; + info.queue_descriptions = queue_descriptions; + return *this; } DeviceBuilder& DeviceBuilder::set_allocation_callbacks(VkAllocationCallbacks* callbacks) { - info.allocation_callbacks = callbacks; - return *this; + info.allocation_callbacks = callbacks; + return *this; } // ---- Swapchain ---- // namespace detail { struct SurfaceSupportDetails { - VkSurfaceCapabilitiesKHR capabilities; - std::vector formats; - std::vector present_modes; + VkSurfaceCapabilitiesKHR capabilities; + std::vector formats; + std::vector present_modes; }; enum class SurfaceSupportError { - surface_handle_null, - failed_get_surface_capabilities, - failed_enumerate_surface_formats, - failed_enumerate_present_modes, - no_suitable_desired_format + surface_handle_null, + failed_get_surface_capabilities, + failed_enumerate_surface_formats, + failed_enumerate_present_modes, + no_suitable_desired_format }; struct SurfaceSupportErrorCategory : std::error_category { - const char* name() const noexcept override { return "vbk_surface_support"; } - std::string message(int err) const override { - switch (static_cast(err)) { - CASE_TO_STRING(SurfaceSupportError, surface_handle_null) - CASE_TO_STRING(SurfaceSupportError, failed_get_surface_capabilities) - CASE_TO_STRING(SurfaceSupportError, failed_enumerate_surface_formats) - CASE_TO_STRING(SurfaceSupportError, failed_enumerate_present_modes) - CASE_TO_STRING(SurfaceSupportError, no_suitable_desired_format) - default: - return ""; - } - } + const char* name() const noexcept override { return "vbk_surface_support"; } + std::string message(int err) const override { + switch (static_cast(err)) { + CASE_TO_STRING(SurfaceSupportError, surface_handle_null) + CASE_TO_STRING(SurfaceSupportError, failed_get_surface_capabilities) + CASE_TO_STRING(SurfaceSupportError, failed_enumerate_surface_formats) + CASE_TO_STRING(SurfaceSupportError, failed_enumerate_present_modes) + CASE_TO_STRING(SurfaceSupportError, no_suitable_desired_format) + default: + return ""; + } + } }; const SurfaceSupportErrorCategory surface_support_error_category; std::error_code make_error_code(SurfaceSupportError surface_support_error) { - return { static_cast(surface_support_error), detail::surface_support_error_category }; + return { static_cast(surface_support_error), detail::surface_support_error_category }; } Result query_surface_support_details(VkPhysicalDevice phys_device, VkSurfaceKHR surface) { - if (surface == VK_NULL_HANDLE) return make_error_code(SurfaceSupportError::surface_handle_null); + if (surface == VK_NULL_HANDLE) return make_error_code(SurfaceSupportError::surface_handle_null); - VkSurfaceCapabilitiesKHR capabilities; - VkResult res = detail::vulkan_functions().fp_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_device, surface, &capabilities); - if (res != VK_SUCCESS) { - return { make_error_code(SurfaceSupportError::failed_get_surface_capabilities), res }; - } + VkSurfaceCapabilitiesKHR capabilities; + VkResult res = detail::vulkan_functions().fp_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_device, surface, &capabilities); + if (res != VK_SUCCESS) { + return { make_error_code(SurfaceSupportError::failed_get_surface_capabilities), res }; + } - std::vector formats; - std::vector present_modes; + std::vector formats; + std::vector present_modes; - auto formats_ret = detail::get_vector( - formats, detail::vulkan_functions().fp_vkGetPhysicalDeviceSurfaceFormatsKHR, phys_device, surface); - if (formats_ret != VK_SUCCESS) - return { make_error_code(SurfaceSupportError::failed_enumerate_surface_formats), formats_ret }; - auto present_modes_ret = detail::get_vector( - present_modes, detail::vulkan_functions().fp_vkGetPhysicalDeviceSurfacePresentModesKHR, phys_device, surface); - if (present_modes_ret != VK_SUCCESS) - return { make_error_code(SurfaceSupportError::failed_enumerate_present_modes), present_modes_ret }; + auto formats_ret = detail::get_vector( + formats, detail::vulkan_functions().fp_vkGetPhysicalDeviceSurfaceFormatsKHR, phys_device, surface); + if (formats_ret != VK_SUCCESS) + return { make_error_code(SurfaceSupportError::failed_enumerate_surface_formats), formats_ret }; + auto present_modes_ret = detail::get_vector( + present_modes, detail::vulkan_functions().fp_vkGetPhysicalDeviceSurfacePresentModesKHR, phys_device, surface); + if (present_modes_ret != VK_SUCCESS) + return { make_error_code(SurfaceSupportError::failed_enumerate_present_modes), present_modes_ret }; - return SurfaceSupportDetails{ capabilities, formats, present_modes }; + return SurfaceSupportDetails{ capabilities, formats, present_modes }; } Result find_desired_surface_format( std::vector const& available_formats, std::vector const& desired_formats) { - for (auto const& desired_format : desired_formats) { - for (auto const& available_format : available_formats) { - // finds the first format that is desired and available - if (desired_format.format == available_format.format && desired_format.colorSpace == available_format.colorSpace) { - return desired_format; - } - } - } + for (auto const& desired_format : desired_formats) { + for (auto const& available_format : available_formats) { + // finds the first format that is desired and available + if (desired_format.format == available_format.format && desired_format.colorSpace == available_format.colorSpace) { + return desired_format; + } + } + } - // if no desired format is available, we report that no format is suitable to the user request - return { make_error_code(SurfaceSupportError::no_suitable_desired_format) }; + // if no desired format is available, we report that no format is suitable to the user request + return { make_error_code(SurfaceSupportError::no_suitable_desired_format) }; } VkSurfaceFormatKHR find_best_surface_format( std::vector const& available_formats, std::vector const& desired_formats) { - auto surface_format_ret = detail::find_desired_surface_format(available_formats, desired_formats); - if (surface_format_ret.has_value()) return surface_format_ret.value(); + auto surface_format_ret = detail::find_desired_surface_format(available_formats, desired_formats); + if (surface_format_ret.has_value()) return surface_format_ret.value(); - // use the first available format as a fallback if any desired formats aren't found - return available_formats[0]; + // use the first available format as a fallback if any desired formats aren't found + return available_formats[0]; } VkPresentModeKHR find_present_mode(std::vector const& available_resent_modes, std::vector const& desired_present_modes) { - for (auto const& desired_pm : desired_present_modes) { - for (auto const& available_pm : available_resent_modes) { - // finds the first present mode that is desired and available - if (desired_pm == available_pm) return desired_pm; - } - } - // only present mode required, use as a fallback - return VK_PRESENT_MODE_FIFO_KHR; + for (auto const& desired_pm : desired_present_modes) { + for (auto const& available_pm : available_resent_modes) { + // finds the first present mode that is desired and available + if (desired_pm == available_pm) return desired_pm; + } + } + // only present mode required, use as a fallback + return VK_PRESENT_MODE_FIFO_KHR; } template T minimum(T a, T b) { return a < b ? a : b; } template T maximum(T a, T b) { return a > b ? a : b; } VkExtent2D find_extent(VkSurfaceCapabilitiesKHR const& capabilities, uint32_t desired_width, uint32_t desired_height) { - if (capabilities.currentExtent.width != UINT32_MAX) { - return capabilities.currentExtent; - } else { - VkExtent2D actualExtent = { desired_width, desired_height }; + if (capabilities.currentExtent.width != UINT32_MAX) { + return capabilities.currentExtent; + } else { + VkExtent2D actualExtent = { desired_width, desired_height }; - actualExtent.width = - maximum(capabilities.minImageExtent.width, minimum(capabilities.maxImageExtent.width, actualExtent.width)); - actualExtent.height = - maximum(capabilities.minImageExtent.height, minimum(capabilities.maxImageExtent.height, actualExtent.height)); + actualExtent.width = + maximum(capabilities.minImageExtent.width, minimum(capabilities.maxImageExtent.width, actualExtent.width)); + actualExtent.height = + maximum(capabilities.minImageExtent.height, minimum(capabilities.maxImageExtent.height, actualExtent.height)); - return actualExtent; - } + return actualExtent; + } } } // namespace detail void destroy_swapchain(Swapchain const& swapchain) { - if (swapchain.device != VK_NULL_HANDLE && swapchain.swapchain != VK_NULL_HANDLE) { - swapchain.internal_table.fp_vkDestroySwapchainKHR(swapchain.device, swapchain.swapchain, swapchain.allocation_callbacks); - } + if (swapchain.device != VK_NULL_HANDLE && swapchain.swapchain != VK_NULL_HANDLE) { + swapchain.internal_table.fp_vkDestroySwapchainKHR(swapchain.device, swapchain.swapchain, swapchain.allocation_callbacks); + } } SwapchainBuilder::SwapchainBuilder(Device const& device) { - info.physical_device = device.physical_device.physical_device; - info.device = device.device; - info.surface = device.surface; - info.instance_version = device.instance_version; - auto present = device.get_queue_index(QueueType::present); - auto graphics = device.get_queue_index(QueueType::graphics); - assert(graphics.has_value() && present.has_value() && "Graphics and Present queue indexes must be valid"); - info.graphics_queue_index = present.value(); - info.present_queue_index = graphics.value(); - info.allocation_callbacks = device.allocation_callbacks; + info.physical_device = device.physical_device.physical_device; + info.device = device.device; + info.surface = device.surface; + info.instance_version = device.instance_version; + auto present = device.get_queue_index(QueueType::present); + auto graphics = device.get_queue_index(QueueType::graphics); + assert(graphics.has_value() && present.has_value() && "Graphics and Present queue indexes must be valid"); + info.graphics_queue_index = present.value(); + info.present_queue_index = graphics.value(); + info.allocation_callbacks = device.allocation_callbacks; } SwapchainBuilder::SwapchainBuilder(Device const& device, VkSurfaceKHR const surface) { - info.physical_device = device.physical_device.physical_device; - info.device = device.device; - info.surface = surface; - info.instance_version = device.instance_version; - Device temp_device = device; - temp_device.surface = surface; - auto present = temp_device.get_queue_index(QueueType::present); - auto graphics = temp_device.get_queue_index(QueueType::graphics); - assert(graphics.has_value() && present.has_value() && "Graphics and Present queue indexes must be valid"); - info.graphics_queue_index = graphics.value(); - info.present_queue_index = present.value(); - info.allocation_callbacks = device.allocation_callbacks; + info.physical_device = device.physical_device.physical_device; + info.device = device.device; + info.surface = surface; + info.instance_version = device.instance_version; + Device temp_device = device; + temp_device.surface = surface; + auto present = temp_device.get_queue_index(QueueType::present); + auto graphics = temp_device.get_queue_index(QueueType::graphics); + assert(graphics.has_value() && present.has_value() && "Graphics and Present queue indexes must be valid"); + info.graphics_queue_index = graphics.value(); + info.present_queue_index = present.value(); + info.allocation_callbacks = device.allocation_callbacks; } SwapchainBuilder::SwapchainBuilder(VkPhysicalDevice const physical_device, VkDevice const device, VkSurfaceKHR const surface, uint32_t graphics_queue_index, uint32_t present_queue_index) { - info.physical_device = physical_device; - info.device = device; - info.surface = surface; - info.graphics_queue_index = graphics_queue_index; - info.present_queue_index = present_queue_index; - if (graphics_queue_index == detail::QUEUE_INDEX_MAX_VALUE || present_queue_index == detail::QUEUE_INDEX_MAX_VALUE) { - auto queue_families = detail::get_vector_noerror( - detail::vulkan_functions().fp_vkGetPhysicalDeviceQueueFamilyProperties, physical_device); - if (graphics_queue_index == detail::QUEUE_INDEX_MAX_VALUE) - info.graphics_queue_index = detail::get_first_queue_index(queue_families, VK_QUEUE_GRAPHICS_BIT); - if (present_queue_index == detail::QUEUE_INDEX_MAX_VALUE) - info.present_queue_index = detail::get_present_queue_index(physical_device, surface, queue_families); - } + info.physical_device = physical_device; + info.device = device; + info.surface = surface; + info.graphics_queue_index = graphics_queue_index; + info.present_queue_index = present_queue_index; + if (graphics_queue_index == detail::QUEUE_INDEX_MAX_VALUE || present_queue_index == detail::QUEUE_INDEX_MAX_VALUE) { + auto queue_families = detail::get_vector_noerror( + detail::vulkan_functions().fp_vkGetPhysicalDeviceQueueFamilyProperties, physical_device); + if (graphics_queue_index == detail::QUEUE_INDEX_MAX_VALUE) + info.graphics_queue_index = detail::get_first_queue_index(queue_families, VK_QUEUE_GRAPHICS_BIT); + if (present_queue_index == detail::QUEUE_INDEX_MAX_VALUE) + info.present_queue_index = detail::get_present_queue_index(physical_device, surface, queue_families); + } } Result SwapchainBuilder::build() const { - if (info.surface == VK_NULL_HANDLE) { - return Error{ SwapchainError::surface_handle_not_provided }; - } + if (info.surface == VK_NULL_HANDLE) { + return Error{ SwapchainError::surface_handle_not_provided }; + } - auto desired_formats = info.desired_formats; - if (desired_formats.size() == 0) add_desired_formats(desired_formats); - auto desired_present_modes = info.desired_present_modes; - if (desired_present_modes.size() == 0) add_desired_present_modes(desired_present_modes); + auto desired_formats = info.desired_formats; + if (desired_formats.size() == 0) add_desired_formats(desired_formats); + auto desired_present_modes = info.desired_present_modes; + if (desired_present_modes.size() == 0) add_desired_present_modes(desired_present_modes); - auto surface_support_ret = detail::query_surface_support_details(info.physical_device, info.surface); - if (!surface_support_ret.has_value()) - return Error{ SwapchainError::failed_query_surface_support_details, surface_support_ret.vk_result() }; - auto surface_support = surface_support_ret.value(); + auto surface_support_ret = detail::query_surface_support_details(info.physical_device, info.surface); + if (!surface_support_ret.has_value()) + return Error{ SwapchainError::failed_query_surface_support_details, surface_support_ret.vk_result() }; + auto surface_support = surface_support_ret.value(); - uint32_t image_count = info.min_image_count; - if (info.required_min_image_count >= 1) { - if (info.required_min_image_count < surface_support.capabilities.minImageCount) - return make_error_code(SwapchainError::required_min_image_count_too_low); + uint32_t image_count = info.min_image_count; + if (info.required_min_image_count >= 1) { + if (info.required_min_image_count < surface_support.capabilities.minImageCount) + return make_error_code(SwapchainError::required_min_image_count_too_low); - image_count = info.required_min_image_count; - } else if (info.min_image_count == 0) { - // We intentionally use minImageCount + 1 to maintain existing behavior, even if it typically results in triple buffering on most systems. - image_count = surface_support.capabilities.minImageCount + 1; - } else { - image_count = info.min_image_count; - if (image_count < surface_support.capabilities.minImageCount) - image_count = surface_support.capabilities.minImageCount; - } - if (surface_support.capabilities.maxImageCount > 0 && image_count > surface_support.capabilities.maxImageCount) { - image_count = surface_support.capabilities.maxImageCount; - } + image_count = info.required_min_image_count; + } else if (info.min_image_count == 0) { + // We intentionally use minImageCount + 1 to maintain existing behavior, even if it typically results in triple buffering on most systems. + image_count = surface_support.capabilities.minImageCount + 1; + } else { + image_count = info.min_image_count; + if (image_count < surface_support.capabilities.minImageCount) + image_count = surface_support.capabilities.minImageCount; + } + if (surface_support.capabilities.maxImageCount > 0 && image_count > surface_support.capabilities.maxImageCount) { + image_count = surface_support.capabilities.maxImageCount; + } - VkSurfaceFormatKHR surface_format = detail::find_best_surface_format(surface_support.formats, desired_formats); + VkSurfaceFormatKHR surface_format = detail::find_best_surface_format(surface_support.formats, desired_formats); - VkExtent2D extent = detail::find_extent(surface_support.capabilities, info.desired_width, info.desired_height); + VkExtent2D extent = detail::find_extent(surface_support.capabilities, info.desired_width, info.desired_height); - uint32_t image_array_layers = info.array_layer_count; - if (surface_support.capabilities.maxImageArrayLayers < info.array_layer_count) - image_array_layers = surface_support.capabilities.maxImageArrayLayers; - if (info.array_layer_count == 0) image_array_layers = 1; + uint32_t image_array_layers = info.array_layer_count; + if (surface_support.capabilities.maxImageArrayLayers < info.array_layer_count) + image_array_layers = surface_support.capabilities.maxImageArrayLayers; + if (info.array_layer_count == 0) image_array_layers = 1; - uint32_t queue_family_indices[] = { info.graphics_queue_index, info.present_queue_index }; + uint32_t queue_family_indices[] = { info.graphics_queue_index, info.present_queue_index }; - VkPresentModeKHR present_mode = detail::find_present_mode(surface_support.present_modes, desired_present_modes); + VkPresentModeKHR present_mode = detail::find_present_mode(surface_support.present_modes, desired_present_modes); - // VkSurfaceCapabilitiesKHR::supportedUsageFlags is only only valid for some present modes. For shared present modes, we should also check VkSharedPresentSurfaceCapabilitiesKHR::sharedPresentSupportedUsageFlags. - auto is_unextended_present_mode = [](VkPresentModeKHR present_mode) { - return (present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR) || (present_mode == VK_PRESENT_MODE_MAILBOX_KHR) || - (present_mode == VK_PRESENT_MODE_FIFO_KHR) || (present_mode == VK_PRESENT_MODE_FIFO_RELAXED_KHR); - }; + // VkSurfaceCapabilitiesKHR::supportedUsageFlags is only only valid for some present modes. For shared present modes, we should also check VkSharedPresentSurfaceCapabilitiesKHR::sharedPresentSupportedUsageFlags. + auto is_unextended_present_mode = [](VkPresentModeKHR present_mode) { + return (present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR) || (present_mode == VK_PRESENT_MODE_MAILBOX_KHR) || + (present_mode == VK_PRESENT_MODE_FIFO_KHR) || (present_mode == VK_PRESENT_MODE_FIFO_RELAXED_KHR); + }; - if (is_unextended_present_mode(present_mode) && - (info.image_usage_flags & surface_support.capabilities.supportedUsageFlags) != info.image_usage_flags) { - return Error{ SwapchainError::required_usage_not_supported }; - } + if (is_unextended_present_mode(present_mode) && + (info.image_usage_flags & surface_support.capabilities.supportedUsageFlags) != info.image_usage_flags) { + return Error{ SwapchainError::required_usage_not_supported }; + } - VkSurfaceTransformFlagBitsKHR pre_transform = info.pre_transform; - if (info.pre_transform == static_cast(0)) - pre_transform = surface_support.capabilities.currentTransform; + VkSurfaceTransformFlagBitsKHR pre_transform = info.pre_transform; + if (info.pre_transform == static_cast(0)) + pre_transform = surface_support.capabilities.currentTransform; - VkSwapchainCreateInfoKHR swapchain_create_info = {}; - swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - detail::setup_pNext_chain(swapchain_create_info, info.pNext_chain); + VkSwapchainCreateInfoKHR swapchain_create_info = {}; + swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + detail::setup_pNext_chain(swapchain_create_info, info.pNext_chain); #if !defined(NDEBUG) - for (auto& node : info.pNext_chain) { - assert(node->sType != VK_STRUCTURE_TYPE_APPLICATION_INFO); - } + for (auto& node : info.pNext_chain) { + assert(node->sType != VK_STRUCTURE_TYPE_APPLICATION_INFO); + } #endif - swapchain_create_info.flags = info.create_flags; - swapchain_create_info.surface = info.surface; - swapchain_create_info.minImageCount = image_count; - swapchain_create_info.imageFormat = surface_format.format; - swapchain_create_info.imageColorSpace = surface_format.colorSpace; - swapchain_create_info.imageExtent = extent; - swapchain_create_info.imageArrayLayers = image_array_layers; - swapchain_create_info.imageUsage = info.image_usage_flags; + swapchain_create_info.flags = info.create_flags; + swapchain_create_info.surface = info.surface; + swapchain_create_info.minImageCount = image_count; + swapchain_create_info.imageFormat = surface_format.format; + swapchain_create_info.imageColorSpace = surface_format.colorSpace; + swapchain_create_info.imageExtent = extent; + swapchain_create_info.imageArrayLayers = image_array_layers; + swapchain_create_info.imageUsage = info.image_usage_flags; - if (info.graphics_queue_index != info.present_queue_index) { - swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT; - swapchain_create_info.queueFamilyIndexCount = 2; - swapchain_create_info.pQueueFamilyIndices = queue_family_indices; - } else { - swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - } + if (info.graphics_queue_index != info.present_queue_index) { + swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT; + swapchain_create_info.queueFamilyIndexCount = 2; + swapchain_create_info.pQueueFamilyIndices = queue_family_indices; + } else { + swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + } - swapchain_create_info.preTransform = pre_transform; - swapchain_create_info.compositeAlpha = info.composite_alpha; - swapchain_create_info.presentMode = present_mode; - swapchain_create_info.clipped = info.clipped; - swapchain_create_info.oldSwapchain = info.old_swapchain; - Swapchain swapchain{}; - PFN_vkCreateSwapchainKHR swapchain_create_proc; - detail::vulkan_functions().get_device_proc_addr(info.device, swapchain_create_proc, "vkCreateSwapchainKHR"); - auto res = swapchain_create_proc(info.device, &swapchain_create_info, info.allocation_callbacks, &swapchain.swapchain); + swapchain_create_info.preTransform = pre_transform; + swapchain_create_info.compositeAlpha = info.composite_alpha; + swapchain_create_info.presentMode = present_mode; + swapchain_create_info.clipped = info.clipped; + swapchain_create_info.oldSwapchain = info.old_swapchain; + Swapchain swapchain{}; + PFN_vkCreateSwapchainKHR swapchain_create_proc; + detail::vulkan_functions().get_device_proc_addr(info.device, swapchain_create_proc, "vkCreateSwapchainKHR"); + auto res = swapchain_create_proc(info.device, &swapchain_create_info, info.allocation_callbacks, &swapchain.swapchain); - if (res != VK_SUCCESS) { - return Error{ SwapchainError::failed_create_swapchain, res }; - } - swapchain.device = info.device; - swapchain.image_format = surface_format.format; - swapchain.color_space = surface_format.colorSpace; - swapchain.image_usage_flags = info.image_usage_flags; - swapchain.extent = extent; - detail::vulkan_functions().get_device_proc_addr( - info.device, swapchain.internal_table.fp_vkGetSwapchainImagesKHR, "vkGetSwapchainImagesKHR"); - detail::vulkan_functions().get_device_proc_addr(info.device, swapchain.internal_table.fp_vkCreateImageView, "vkCreateImageView"); - detail::vulkan_functions().get_device_proc_addr(info.device, swapchain.internal_table.fp_vkDestroyImageView, "vkDestroyImageView"); - detail::vulkan_functions().get_device_proc_addr( - info.device, swapchain.internal_table.fp_vkDestroySwapchainKHR, "vkDestroySwapchainKHR"); - auto images = swapchain.get_images(); - if (!images) { - return Error{ SwapchainError::failed_get_swapchain_images }; - } - swapchain.requested_min_image_count = image_count; - swapchain.present_mode = present_mode; - swapchain.image_count = static_cast(images.value().size()); - swapchain.instance_version = info.instance_version; - swapchain.allocation_callbacks = info.allocation_callbacks; - return swapchain; + if (res != VK_SUCCESS) { + return Error{ SwapchainError::failed_create_swapchain, res }; + } + swapchain.device = info.device; + swapchain.image_format = surface_format.format; + swapchain.color_space = surface_format.colorSpace; + swapchain.image_usage_flags = info.image_usage_flags; + swapchain.extent = extent; + detail::vulkan_functions().get_device_proc_addr( + info.device, swapchain.internal_table.fp_vkGetSwapchainImagesKHR, "vkGetSwapchainImagesKHR"); + detail::vulkan_functions().get_device_proc_addr(info.device, swapchain.internal_table.fp_vkCreateImageView, "vkCreateImageView"); + detail::vulkan_functions().get_device_proc_addr(info.device, swapchain.internal_table.fp_vkDestroyImageView, "vkDestroyImageView"); + detail::vulkan_functions().get_device_proc_addr( + info.device, swapchain.internal_table.fp_vkDestroySwapchainKHR, "vkDestroySwapchainKHR"); + auto images = swapchain.get_images(); + if (!images) { + return Error{ SwapchainError::failed_get_swapchain_images }; + } + swapchain.requested_min_image_count = image_count; + swapchain.present_mode = present_mode; + swapchain.image_count = static_cast(images.value().size()); + swapchain.instance_version = info.instance_version; + swapchain.allocation_callbacks = info.allocation_callbacks; + return swapchain; } Result> Swapchain::get_images() { - std::vector swapchain_images; + std::vector swapchain_images; - auto swapchain_images_ret = - detail::get_vector(swapchain_images, internal_table.fp_vkGetSwapchainImagesKHR, device, swapchain); - if (swapchain_images_ret != VK_SUCCESS) { - return Error{ SwapchainError::failed_get_swapchain_images, swapchain_images_ret }; - } - return swapchain_images; + auto swapchain_images_ret = + detail::get_vector(swapchain_images, internal_table.fp_vkGetSwapchainImagesKHR, device, swapchain); + if (swapchain_images_ret != VK_SUCCESS) { + return Error{ SwapchainError::failed_get_swapchain_images, swapchain_images_ret }; + } + return swapchain_images; } Result> Swapchain::get_image_views() { return get_image_views(nullptr); } Result> Swapchain::get_image_views(const void* pNext) { - const auto swapchain_images_ret = get_images(); - if (!swapchain_images_ret) return swapchain_images_ret.error(); - const auto swapchain_images = swapchain_images_ret.value(); + const auto swapchain_images_ret = get_images(); + if (!swapchain_images_ret) return swapchain_images_ret.error(); + const auto swapchain_images = swapchain_images_ret.value(); - bool already_contains_image_view_usage = false; - while (pNext) { - if (reinterpret_cast(pNext)->sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO) { - already_contains_image_view_usage = true; - break; - } - pNext = reinterpret_cast(pNext)->pNext; - } - VkImageViewUsageCreateInfo desired_flags{}; - desired_flags.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO; - desired_flags.pNext = pNext; - desired_flags.usage = image_usage_flags; + bool already_contains_image_view_usage = false; + while (pNext) { + if (reinterpret_cast(pNext)->sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO) { + already_contains_image_view_usage = true; + break; + } + pNext = reinterpret_cast(pNext)->pNext; + } + VkImageViewUsageCreateInfo desired_flags{}; + desired_flags.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO; + desired_flags.pNext = pNext; + desired_flags.usage = image_usage_flags; - std::vector views(swapchain_images.size()); - for (size_t i = 0; i < swapchain_images.size(); i++) { - VkImageViewCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - if (instance_version >= VKB_VK_API_VERSION_1_1 && !already_contains_image_view_usage) { - createInfo.pNext = &desired_flags; - } else { - createInfo.pNext = pNext; - } + std::vector views(swapchain_images.size()); + for (size_t i = 0; i < swapchain_images.size(); i++) { + VkImageViewCreateInfo createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + if (instance_version >= VKB_VK_API_VERSION_1_1 && !already_contains_image_view_usage) { + createInfo.pNext = &desired_flags; + } else { + createInfo.pNext = pNext; + } - createInfo.image = swapchain_images[i]; - createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - createInfo.format = image_format; - createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - createInfo.subresourceRange.baseMipLevel = 0; - createInfo.subresourceRange.levelCount = 1; - createInfo.subresourceRange.baseArrayLayer = 0; - createInfo.subresourceRange.layerCount = 1; - VkResult res = internal_table.fp_vkCreateImageView(device, &createInfo, allocation_callbacks, &views[i]); - if (res != VK_SUCCESS) return Error{ SwapchainError::failed_create_swapchain_image_views, res }; - } - return views; + createInfo.image = swapchain_images[i]; + createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + createInfo.format = image_format; + createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + createInfo.subresourceRange.baseMipLevel = 0; + createInfo.subresourceRange.levelCount = 1; + createInfo.subresourceRange.baseArrayLayer = 0; + createInfo.subresourceRange.layerCount = 1; + VkResult res = internal_table.fp_vkCreateImageView(device, &createInfo, allocation_callbacks, &views[i]); + if (res != VK_SUCCESS) return Error{ SwapchainError::failed_create_swapchain_image_views, res }; + } + return views; } void Swapchain::destroy_image_views(std::vector const& image_views) { - for (auto& image_view : image_views) { - internal_table.fp_vkDestroyImageView(device, image_view, allocation_callbacks); - } + for (auto& image_view : image_views) { + internal_table.fp_vkDestroyImageView(device, image_view, allocation_callbacks); + } } Swapchain::operator VkSwapchainKHR() const { return this->swapchain; } SwapchainBuilder& SwapchainBuilder::set_old_swapchain(VkSwapchainKHR old_swapchain) { - info.old_swapchain = old_swapchain; - return *this; + info.old_swapchain = old_swapchain; + return *this; } SwapchainBuilder& SwapchainBuilder::set_old_swapchain(Swapchain const& swapchain) { - info.old_swapchain = swapchain.swapchain; - return *this; + info.old_swapchain = swapchain.swapchain; + return *this; } SwapchainBuilder& SwapchainBuilder::set_desired_extent(uint32_t width, uint32_t height) { - info.desired_width = width; - info.desired_height = height; - return *this; + info.desired_width = width; + info.desired_height = height; + return *this; } SwapchainBuilder& SwapchainBuilder::set_desired_format(VkSurfaceFormatKHR format) { - info.desired_formats.insert(info.desired_formats.begin(), format); - return *this; + info.desired_formats.insert(info.desired_formats.begin(), format); + return *this; } SwapchainBuilder& SwapchainBuilder::add_fallback_format(VkSurfaceFormatKHR format) { - info.desired_formats.push_back(format); - return *this; + info.desired_formats.push_back(format); + return *this; } SwapchainBuilder& SwapchainBuilder::use_default_format_selection() { - info.desired_formats.clear(); - add_desired_formats(info.desired_formats); - return *this; + info.desired_formats.clear(); + add_desired_formats(info.desired_formats); + return *this; } SwapchainBuilder& SwapchainBuilder::set_desired_present_mode(VkPresentModeKHR present_mode) { - info.desired_present_modes.insert(info.desired_present_modes.begin(), present_mode); - return *this; + info.desired_present_modes.insert(info.desired_present_modes.begin(), present_mode); + return *this; } SwapchainBuilder& SwapchainBuilder::add_fallback_present_mode(VkPresentModeKHR present_mode) { - info.desired_present_modes.push_back(present_mode); - return *this; + info.desired_present_modes.push_back(present_mode); + return *this; } SwapchainBuilder& SwapchainBuilder::use_default_present_mode_selection() { - info.desired_present_modes.clear(); - add_desired_present_modes(info.desired_present_modes); - return *this; + info.desired_present_modes.clear(); + add_desired_present_modes(info.desired_present_modes); + return *this; } SwapchainBuilder& SwapchainBuilder::set_allocation_callbacks(VkAllocationCallbacks* callbacks) { - info.allocation_callbacks = callbacks; - return *this; + info.allocation_callbacks = callbacks; + return *this; } SwapchainBuilder& SwapchainBuilder::set_image_usage_flags(VkImageUsageFlags usage_flags) { - info.image_usage_flags = usage_flags; - return *this; + info.image_usage_flags = usage_flags; + return *this; } SwapchainBuilder& SwapchainBuilder::add_image_usage_flags(VkImageUsageFlags usage_flags) { - info.image_usage_flags = info.image_usage_flags | usage_flags; - return *this; + info.image_usage_flags = info.image_usage_flags | usage_flags; + return *this; } SwapchainBuilder& SwapchainBuilder::use_default_image_usage_flags() { - info.image_usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - return *this; + info.image_usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + return *this; } SwapchainBuilder& SwapchainBuilder::set_image_array_layer_count(uint32_t array_layer_count) { - info.array_layer_count = array_layer_count; - return *this; + info.array_layer_count = array_layer_count; + return *this; } SwapchainBuilder& SwapchainBuilder::set_desired_min_image_count(uint32_t min_image_count) { - info.min_image_count = min_image_count; - return *this; + info.min_image_count = min_image_count; + return *this; } SwapchainBuilder& SwapchainBuilder::set_required_min_image_count(uint32_t required_min_image_count) { - info.required_min_image_count = required_min_image_count; - return *this; + info.required_min_image_count = required_min_image_count; + return *this; } SwapchainBuilder& SwapchainBuilder::set_clipped(bool clipped) { - info.clipped = clipped; - return *this; + info.clipped = clipped; + return *this; } SwapchainBuilder& SwapchainBuilder::set_create_flags(VkSwapchainCreateFlagBitsKHR create_flags) { - info.create_flags = create_flags; - return *this; + info.create_flags = create_flags; + return *this; } SwapchainBuilder& SwapchainBuilder::set_pre_transform_flags(VkSurfaceTransformFlagBitsKHR pre_transform_flags) { - info.pre_transform = pre_transform_flags; - return *this; + info.pre_transform = pre_transform_flags; + return *this; } SwapchainBuilder& SwapchainBuilder::set_composite_alpha_flags(VkCompositeAlphaFlagBitsKHR composite_alpha_flags) { - info.composite_alpha = composite_alpha_flags; - return *this; + info.composite_alpha = composite_alpha_flags; + return *this; } void SwapchainBuilder::add_desired_formats(std::vector& formats) const { - formats.push_back({ VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }); - formats.push_back({ VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }); + formats.push_back({ VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }); + formats.push_back({ VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR }); } void SwapchainBuilder::add_desired_present_modes(std::vector& modes) const { - modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR); - modes.push_back(VK_PRESENT_MODE_FIFO_KHR); + modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR); + modes.push_back(VK_PRESENT_MODE_FIFO_KHR); } } // namespace vkb diff --git a/src/VkBootstrap.h b/src/VkBootstrap.h index ef77c2a..fa7355d 100644 --- a/src/VkBootstrap.h +++ b/src/VkBootstrap.h @@ -53,73 +53,73 @@ namespace vkb { struct Error { - std::error_code type; - VkResult vk_result = VK_SUCCESS; // optional error value if a vulkan call failed + std::error_code type; + VkResult vk_result = VK_SUCCESS; // optional error value if a vulkan call failed }; template class Result { - public: - Result(const T& value) noexcept : m_value{ value }, m_init{ true } {} - Result(T&& value) noexcept : m_value{ std::move(value) }, m_init{ true } {} + public: + Result(const T& value) noexcept : m_value{ value }, m_init{ true } {} + Result(T&& value) noexcept : m_value{ std::move(value) }, m_init{ true } {} - Result(Error error) noexcept : m_error{ error }, m_init{ false } {} + Result(Error error) noexcept : m_error{ error }, m_init{ false } {} - Result(std::error_code error_code, VkResult result = VK_SUCCESS) noexcept - : m_error{ error_code, result }, m_init{ false } {} + Result(std::error_code error_code, VkResult result = VK_SUCCESS) noexcept + : m_error{ error_code, result }, m_init{ false } {} - ~Result() noexcept { destroy(); } - Result(Result const& expected) noexcept : m_init(expected.m_init) { - if (m_init) - new (&m_value) T{ expected.m_value }; - else - m_error = expected.m_error; - } - Result& operator=(Result const& result) noexcept { - m_init = result.m_init; - if (m_init) - new (&m_value) T{ result.m_value }; - else - m_error = result.m_error; - } - Result(Result&& expected) noexcept : m_init(expected.m_init) { - if (m_init) - new (&m_value) T{ std::move(expected.m_value) }; - else - m_error = std::move(expected.m_error); - expected.destroy(); - } - Result& operator=(Result&& result) noexcept { - m_init = result.m_init; - if (m_init) - new (&m_value) T{ std::move(result.m_value) }; - else - m_error = std::move(result.m_error); - } - Result& operator=(const T& expect) noexcept { - destroy(); - m_init = true; - new (&m_value) T{ expect }; - return *this; - } - Result& operator=(T&& expect) noexcept { - destroy(); - m_init = true; - new (&m_value) T{ std::move(expect) }; - return *this; - } - Result& operator=(const Error& error) noexcept { - destroy(); - m_init = false; - m_error = error; - return *this; - } - Result& operator=(Error&& error) noexcept { - destroy(); - m_init = false; - m_error = error; - return *this; - } - // clang-format off + ~Result() noexcept { destroy(); } + Result(Result const& expected) noexcept : m_init(expected.m_init) { + if (m_init) + new (&m_value) T{ expected.m_value }; + else + m_error = expected.m_error; + } + Result& operator=(Result const& result) noexcept { + m_init = result.m_init; + if (m_init) + new (&m_value) T{ result.m_value }; + else + m_error = result.m_error; + } + Result(Result&& expected) noexcept : m_init(expected.m_init) { + if (m_init) + new (&m_value) T{ std::move(expected.m_value) }; + else + m_error = std::move(expected.m_error); + expected.destroy(); + } + Result& operator=(Result&& result) noexcept { + m_init = result.m_init; + if (m_init) + new (&m_value) T{ std::move(result.m_value) }; + else + m_error = std::move(result.m_error); + } + Result& operator=(const T& expect) noexcept { + destroy(); + m_init = true; + new (&m_value) T{ expect }; + return *this; + } + Result& operator=(T&& expect) noexcept { + destroy(); + m_init = true; + new (&m_value) T{ std::move(expect) }; + return *this; + } + Result& operator=(const Error& error) noexcept { + destroy(); + m_init = false; + m_error = error; + return *this; + } + Result& operator=(Error&& error) noexcept { + destroy(); + m_init = false; + m_error = error; + return *this; + } + // clang-format off const T* operator-> () const noexcept { assert (m_init); return &m_value; } T* operator-> () noexcept { assert (m_init); return &m_value; } const T& operator* () const& noexcept { assert (m_init); return m_value; } @@ -136,85 +136,85 @@ template class Result { VkResult vk_result() const { assert (!m_init); return m_error.vk_result; } // Returns the struct that holds the std::error_code and VkResult Error full_error() const { assert (!m_init); return m_error; } - // clang-format on + // clang-format on - // check if the result has an error that matches a specific error case - template bool matches_error(E error_enum_value) const { - return !m_init && static_cast(m_error.type.value()) == error_enum_value; - } + // check if the result has an error that matches a specific error case + template bool matches_error(E error_enum_value) const { + return !m_init && static_cast(m_error.type.value()) == error_enum_value; + } - bool has_value() const { return m_init; } - explicit operator bool() const { return m_init; } + bool has_value() const { return m_init; } + explicit operator bool() const { return m_init; } - private: - void destroy() { - if (m_init) m_value.~T(); - } - union { - T m_value; - Error m_error; - }; - bool m_init; + private: + void destroy() { + if (m_init) m_value.~T(); + } + union { + T m_value; + Error m_error; + }; + bool m_init; }; namespace detail { struct GenericFeaturesPNextNode { - static const uint32_t field_capacity = 256; + static const uint32_t field_capacity = 256; - GenericFeaturesPNextNode(); + GenericFeaturesPNextNode(); - template GenericFeaturesPNextNode(T const& features) noexcept { - memset(fields, UINT8_MAX, sizeof(VkBool32) * field_capacity); - memcpy(this, &features, sizeof(T)); - } + template GenericFeaturesPNextNode(T const& features) noexcept { + memset(fields, UINT8_MAX, sizeof(VkBool32) * field_capacity); + memcpy(this, &features, sizeof(T)); + } - static bool match(GenericFeaturesPNextNode const& requested, GenericFeaturesPNextNode const& supported) noexcept; + static bool match(GenericFeaturesPNextNode const& requested, GenericFeaturesPNextNode const& supported) noexcept; - VkStructureType sType = static_cast(0); - void* pNext = nullptr; - VkBool32 fields[field_capacity]; + VkStructureType sType = static_cast(0); + void* pNext = nullptr; + VkBool32 fields[field_capacity]; }; } // 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, + 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, + 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 + present_unavailable, + graphics_unavailable, + compute_unavailable, + transfer_unavailable, + queue_index_out_of_range, + invalid_queue_family_index }; enum class DeviceError { - failed_create_device, - VkPhysicalDeviceFeatures2_in_pNext_chain_while_using_add_required_extension_features, + failed_create_device, + VkPhysicalDeviceFeatures2_in_pNext_chain_while_using_add_required_extension_features, }; enum class SwapchainError { - surface_handle_not_provided, - failed_query_surface_support_details, - failed_create_swapchain, - failed_get_swapchain_images, - failed_create_swapchain_image_views, - required_min_image_count_too_low, - required_usage_not_supported + surface_handle_not_provided, + failed_query_surface_support_details, + failed_create_swapchain, + failed_get_swapchain_images, + failed_create_swapchain_image_views, + required_min_image_count_too_low, + required_usage_not_supported }; std::error_code make_error_code(InstanceError instance_error); @@ -236,23 +236,23 @@ const char* to_string(SwapchainError err); // 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(); + private: + SystemInfo(); - public: - // Use get_system_info to create a SystemInfo struct. This is because loading vulkan could fail. - static Result get_system_info(); - static Result get_system_info(PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr); + public: + // Use get_system_info to create a SystemInfo struct. This is because loading vulkan could fail. + static Result get_system_info(); + static Result 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; + // 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 available_layers; - std::vector available_extensions; - bool validation_layers_available = false; - bool debug_utils_available = false; + std::vector available_layers; + std::vector available_extensions; + bool validation_layers_available = false; + bool debug_utils_available = false; }; // Forward declared - check VkBoostrap.cpp for implementations @@ -265,35 +265,35 @@ inline VKAPI_ATTR VkBool32 VKAPI_CALL default_debug_callback(VkDebugUtilsMessage VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void*) { - auto ms = to_string_message_severity(messageSeverity); - auto mt = to_string_message_type(messageType); - printf("[%s: %s]\n%s\n", ms, mt, pCallbackData->pMessage); + auto ms = to_string_message_severity(messageSeverity); + auto mt = to_string_message_type(messageType); + printf("[%s: %s]\n%s\n", ms, mt, pCallbackData->pMessage); - return VK_FALSE; // Applications must return false here + return VK_FALSE; // Applications must return false here } class InstanceBuilder; class PhysicalDeviceSelector; struct Instance { - VkInstance instance = VK_NULL_HANDLE; - VkDebugUtilsMessengerEXT debug_messenger = VK_NULL_HANDLE; - VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE; - PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr = nullptr; - PFN_vkGetDeviceProcAddr fp_vkGetDeviceProcAddr = nullptr; + VkInstance instance = VK_NULL_HANDLE; + VkDebugUtilsMessengerEXT debug_messenger = VK_NULL_HANDLE; + VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE; + PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr = nullptr; + PFN_vkGetDeviceProcAddr fp_vkGetDeviceProcAddr = nullptr; - // A conversion function which allows this Instance to be used - // in places where VkInstance would have been used. - operator VkInstance() const; + // A conversion function which allows this Instance to be used + // in places where VkInstance would have been used. + operator VkInstance() const; - private: - bool headless = false; - bool properties2_ext_enabled = false; - uint32_t instance_version = VKB_VK_API_VERSION_1_0; - uint32_t api_version = VKB_VK_API_VERSION_1_0; + private: + bool headless = false; + bool properties2_ext_enabled = false; + uint32_t instance_version = VKB_VK_API_VERSION_1_0; + uint32_t api_version = VKB_VK_API_VERSION_1_0; - friend class InstanceBuilder; - friend class PhysicalDeviceSelector; + friend class InstanceBuilder; + friend class PhysicalDeviceSelector; }; void destroy_surface(Instance instance, VkSurfaceKHR surface); // release surface handle @@ -321,137 +321,137 @@ Feel free to make a PR or raise an issue to include additional platforms. */ class InstanceBuilder { - public: - // Default constructor, will load vulkan. - explicit InstanceBuilder(); - // Optional: Can use your own PFN_vkGetInstanceProcAddr - explicit InstanceBuilder(PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr); + public: + // Default constructor, will load vulkan. + explicit InstanceBuilder(); + // Optional: Can use your own PFN_vkGetInstanceProcAddr + explicit InstanceBuilder(PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr); - // Create a VkInstance. Return an error if it failed. - Result build() const; + // Create a VkInstance. Return an error if it failed. + Result build() const; - // Sets the name of the application. Defaults to "" if none is provided. - InstanceBuilder& set_app_name(const char* app_name); - // Sets the name of the engine. Defaults to "" if none is provided. - InstanceBuilder& set_engine_name(const char* engine_name); + // Sets the name of the application. Defaults to "" if none is provided. + InstanceBuilder& set_app_name(const char* app_name); + // Sets the name of the engine. Defaults to "" if none is provided. + InstanceBuilder& set_engine_name(const char* engine_name); - // Sets the version of the application. - // Should be constructed with VK_MAKE_VERSION or VK_MAKE_API_VERSION. - InstanceBuilder& set_app_version(uint32_t app_version); - // Sets the (major, minor, patch) version of the application. - InstanceBuilder& set_app_version(uint32_t major, uint32_t minor, uint32_t patch = 0); + // Sets the version of the application. + // Should be constructed with VK_MAKE_VERSION or VK_MAKE_API_VERSION. + InstanceBuilder& set_app_version(uint32_t app_version); + // Sets the (major, minor, patch) version of the application. + InstanceBuilder& set_app_version(uint32_t major, uint32_t minor, uint32_t patch = 0); - // Sets the version of the engine. - // Should be constructed with VK_MAKE_VERSION or VK_MAKE_API_VERSION. - InstanceBuilder& set_engine_version(uint32_t engine_version); - // Sets the (major, minor, patch) version of the engine. - InstanceBuilder& set_engine_version(uint32_t major, uint32_t minor, uint32_t patch = 0); + // Sets the version of the engine. + // Should be constructed with VK_MAKE_VERSION or VK_MAKE_API_VERSION. + InstanceBuilder& set_engine_version(uint32_t engine_version); + // Sets the (major, minor, patch) version of the engine. + InstanceBuilder& set_engine_version(uint32_t major, uint32_t minor, uint32_t patch = 0); - // Require a vulkan API version. Will fail to create if this version isn't available. - // Should be constructed with VK_MAKE_VERSION or VK_MAKE_API_VERSION. - InstanceBuilder& require_api_version(uint32_t required_api_version); - // Require a vulkan API version. Will fail to create if this version isn't available. - InstanceBuilder& require_api_version(uint32_t major, uint32_t minor, uint32_t patch = 0); + // Require a vulkan API version. Will fail to create if this version isn't available. + // Should be constructed with VK_MAKE_VERSION or VK_MAKE_API_VERSION. + InstanceBuilder& require_api_version(uint32_t required_api_version); + // Require a vulkan API version. Will fail to create if this version isn't available. + InstanceBuilder& require_api_version(uint32_t major, uint32_t minor, uint32_t patch = 0); - // Overrides required API version for instance creation. Will fail to create if this version isn't available. - // Should be constructed with VK_MAKE_VERSION or VK_MAKE_API_VERSION. - InstanceBuilder& set_minimum_instance_version(uint32_t minimum_instance_version); - // Overrides required API version for instance creation. Will fail to create if this version isn't available. - InstanceBuilder& set_minimum_instance_version(uint32_t major, uint32_t minor, uint32_t patch = 0); + // Overrides required API version for instance creation. Will fail to create if this version isn't available. + // Should be constructed with VK_MAKE_VERSION or VK_MAKE_API_VERSION. + InstanceBuilder& set_minimum_instance_version(uint32_t minimum_instance_version); + // Overrides required API version for instance creation. Will fail to create if this version isn't available. + InstanceBuilder& set_minimum_instance_version(uint32_t major, uint32_t minor, uint32_t patch = 0); - // Prefer a vulkan instance API version. If the desired version isn't available, it will use the - // highest version available. Should be constructed with VK_MAKE_VERSION or VK_MAKE_API_VERSION. - [[deprecated("Use require_api_version + set_minimum_instance_version instead.")]] InstanceBuilder& - desire_api_version(uint32_t preferred_vulkan_version); + // Prefer a vulkan instance API version. If the desired version isn't available, it will use the + // highest version available. Should be constructed with VK_MAKE_VERSION or VK_MAKE_API_VERSION. + [[deprecated("Use require_api_version + set_minimum_instance_version instead.")]] InstanceBuilder& + desire_api_version(uint32_t preferred_vulkan_version); - // Prefer a vulkan instance API version. If the desired version isn't available, it will use the highest version available. - [[deprecated("Use require_api_version + set_minimum_instance_version instead.")]] InstanceBuilder& - desire_api_version(uint32_t major, uint32_t minor, uint32_t patch = 0); + // Prefer a vulkan instance API version. If the desired version isn't available, it will use the highest version available. + [[deprecated("Use require_api_version + set_minimum_instance_version instead.")]] InstanceBuilder& + desire_api_version(uint32_t major, uint32_t minor, uint32_t patch = 0); - // Adds a layer to be enabled. Will fail to create an instance if the layer isn't available. - InstanceBuilder& enable_layer(const char* layer_name); - // Adds an extension to be enabled. Will fail to create an instance if the extension isn't available. - InstanceBuilder& enable_extension(const char* extension_name); + // Adds a layer to be enabled. Will fail to create an instance if the layer isn't available. + InstanceBuilder& enable_layer(const char* layer_name); + // Adds an extension to be enabled. Will fail to create an instance if the extension isn't available. + InstanceBuilder& enable_extension(const char* extension_name); - // Headless Mode does not load the required extensions for presentation. Defaults to true. - InstanceBuilder& set_headless(bool headless = true); + // Headless Mode does not load the required extensions for presentation. Defaults to true. + InstanceBuilder& set_headless(bool headless = true); - // Enables the validation layers. Will fail to create an instance if the validation layers aren't available. - InstanceBuilder& 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); + // Enables the validation layers. Will fail to create an instance if the validation layers aren't available. + InstanceBuilder& 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& use_default_debug_messenger(); - // Provide a user defined debug callback. - InstanceBuilder& set_debug_callback(PFN_vkDebugUtilsMessengerCallbackEXT callback); - // Sets the void* to use in the debug messenger - only useful with a custom callback - InstanceBuilder& set_debug_callback_user_data_pointer(void* user_data_pointer); - // Set what message severity is needed to trigger the callback. - InstanceBuilder& set_debug_messenger_severity(VkDebugUtilsMessageSeverityFlagsEXT severity); - // Add a message severity to the list that triggers the callback. - InstanceBuilder& add_debug_messenger_severity(VkDebugUtilsMessageSeverityFlagsEXT severity); - // Set what message type triggers the callback. - InstanceBuilder& set_debug_messenger_type(VkDebugUtilsMessageTypeFlagsEXT type); - // Add a message type to the list of that triggers the callback. - InstanceBuilder& add_debug_messenger_type(VkDebugUtilsMessageTypeFlagsEXT type); + // Use a default debug callback that prints to standard out. + InstanceBuilder& use_default_debug_messenger(); + // Provide a user defined debug callback. + InstanceBuilder& set_debug_callback(PFN_vkDebugUtilsMessengerCallbackEXT callback); + // Sets the void* to use in the debug messenger - only useful with a custom callback + InstanceBuilder& set_debug_callback_user_data_pointer(void* user_data_pointer); + // Set what message severity is needed to trigger the callback. + InstanceBuilder& set_debug_messenger_severity(VkDebugUtilsMessageSeverityFlagsEXT severity); + // Add a message severity to the list that triggers the callback. + InstanceBuilder& add_debug_messenger_severity(VkDebugUtilsMessageSeverityFlagsEXT severity); + // Set what message type triggers the callback. + InstanceBuilder& set_debug_messenger_type(VkDebugUtilsMessageTypeFlagsEXT type); + // Add a message type to the list of that triggers the callback. + InstanceBuilder& add_debug_messenger_type(VkDebugUtilsMessageTypeFlagsEXT type); - // Disable some validation checks. - // Checks: All, and Shaders - InstanceBuilder& add_validation_disable(VkValidationCheckEXT check); + // Disable some validation checks. + // Checks: All, and Shaders + InstanceBuilder& add_validation_disable(VkValidationCheckEXT check); - // Enables optional parts of the validation layers. - // Parts: best practices, gpu assisted, and gpu assisted reserve binding slot. - InstanceBuilder& add_validation_feature_enable(VkValidationFeatureEnableEXT enable); + // Enables optional parts of the validation layers. + // Parts: best practices, gpu assisted, and gpu assisted reserve binding slot. + InstanceBuilder& add_validation_feature_enable(VkValidationFeatureEnableEXT enable); - // Disables sections of the validation layers. - // Options: All, shaders, thread safety, api parameters, object lifetimes, core checks, and unique handles. - InstanceBuilder& add_validation_feature_disable(VkValidationFeatureDisableEXT disable); + // Disables sections of the validation layers. + // Options: All, shaders, thread safety, api parameters, object lifetimes, core checks, and unique handles. + InstanceBuilder& add_validation_feature_disable(VkValidationFeatureDisableEXT disable); - // Provide custom allocation callbacks. - InstanceBuilder& set_allocation_callbacks(VkAllocationCallbacks* callbacks); + // Provide custom allocation callbacks. + InstanceBuilder& set_allocation_callbacks(VkAllocationCallbacks* callbacks); - private: - struct InstanceInfo { - // VkApplicationInfo - const char* app_name = nullptr; - const char* engine_name = nullptr; - uint32_t application_version = 0; - uint32_t engine_version = 0; - uint32_t minimum_instance_version = 0; - uint32_t required_api_version = VKB_VK_API_VERSION_1_0; - uint32_t desired_api_version = VKB_VK_API_VERSION_1_0; + private: + struct InstanceInfo { + // VkApplicationInfo + const char* app_name = nullptr; + const char* engine_name = nullptr; + uint32_t application_version = 0; + uint32_t engine_version = 0; + uint32_t minimum_instance_version = 0; + uint32_t required_api_version = VKB_VK_API_VERSION_1_0; + uint32_t desired_api_version = VKB_VK_API_VERSION_1_0; - // VkInstanceCreateInfo - std::vector layers; - std::vector extensions; - VkInstanceCreateFlags flags = static_cast(0); - std::vector pNext_elements; + // VkInstanceCreateInfo + std::vector layers; + std::vector extensions; + VkInstanceCreateFlags flags = static_cast(0); + std::vector pNext_elements; - // debug callback - use the default so it is not nullptr - PFN_vkDebugUtilsMessengerCallbackEXT debug_callback = default_debug_callback; - VkDebugUtilsMessageSeverityFlagsEXT debug_message_severity = - VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; - VkDebugUtilsMessageTypeFlagsEXT debug_message_type = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; - void* debug_user_data_pointer = nullptr; + // debug callback - use the default so it is not nullptr + PFN_vkDebugUtilsMessengerCallbackEXT debug_callback = default_debug_callback; + VkDebugUtilsMessageSeverityFlagsEXT debug_message_severity = + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + VkDebugUtilsMessageTypeFlagsEXT debug_message_type = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + void* debug_user_data_pointer = nullptr; - // validation features - std::vector disabled_validation_checks; - std::vector enabled_validation_features; - std::vector disabled_validation_features; + // validation features + std::vector disabled_validation_checks; + std::vector enabled_validation_features; + std::vector disabled_validation_features; - // Custom allocator - VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE; + // Custom allocator + VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE; - bool request_validation_layers = false; - bool enable_validation_layers = false; - bool use_debug_messenger = false; - bool headless_context = false; + bool request_validation_layers = false; + bool enable_validation_layers = false; + bool use_debug_messenger = false; + bool headless_context = false; - PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr = nullptr; - } info; + PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr = nullptr; + } info; }; VKAPI_ATTR VkBool32 VKAPI_CALL default_debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, @@ -467,208 +467,208 @@ class PhysicalDeviceSelector; class DeviceBuilder; struct PhysicalDevice { - std::string name; - VkPhysicalDevice physical_device = VK_NULL_HANDLE; - VkSurfaceKHR surface = VK_NULL_HANDLE; + std::string name; + VkPhysicalDevice physical_device = VK_NULL_HANDLE; + VkSurfaceKHR surface = VK_NULL_HANDLE; - // Note that this reflects selected features carried over from required features, not all features the physical device supports. - VkPhysicalDeviceFeatures features{}; - VkPhysicalDeviceProperties properties{}; - VkPhysicalDeviceMemoryProperties memory_properties{}; + // Note that this reflects selected features carried over from required features, not all features the physical device supports. + VkPhysicalDeviceFeatures features{}; + VkPhysicalDeviceProperties properties{}; + VkPhysicalDeviceMemoryProperties memory_properties{}; - // Has a queue family that supports compute operations but not graphics nor transfer. - bool has_dedicated_compute_queue() const; - // Has a queue family that supports transfer operations but not graphics nor compute. - bool has_dedicated_transfer_queue() const; + // Has a queue family that supports compute operations but not graphics nor transfer. + bool has_dedicated_compute_queue() const; + // Has a queue family that supports transfer operations but not graphics nor compute. + bool has_dedicated_transfer_queue() const; - // Has a queue family that supports transfer operations but not graphics. - bool has_separate_compute_queue() const; - // Has a queue family that supports transfer operations but not graphics. - bool has_separate_transfer_queue() const; + // Has a queue family that supports transfer operations but not graphics. + bool has_separate_compute_queue() const; + // Has a queue family that supports transfer operations but not graphics. + bool has_separate_transfer_queue() const; - // Advanced: Get the VkQueueFamilyProperties of the device if special queue setup is needed - std::vector get_queue_families() const; + // Advanced: Get the VkQueueFamilyProperties of the device if special queue setup is needed + std::vector get_queue_families() const; - // Query the list of extensions which should be enabled - std::vector get_extensions() const; + // Query the list of extensions which should be enabled + std::vector get_extensions() const; - // A conversion function which allows this PhysicalDevice to be used - // in places where VkPhysicalDevice would have been used. - operator VkPhysicalDevice() const; + // A conversion function which allows this PhysicalDevice to be used + // in places where VkPhysicalDevice would have been used. + operator VkPhysicalDevice() const; - private: - uint32_t instance_version = VKB_VK_API_VERSION_1_0; - std::vector extensions; - std::vector queue_families; - std::vector extended_features_chain; - VkPhysicalDeviceFeatures2 features2{}; + private: + uint32_t instance_version = VKB_VK_API_VERSION_1_0; + std::vector extensions; + std::vector queue_families; + std::vector extended_features_chain; + VkPhysicalDeviceFeatures2 features2{}; - bool defer_surface_initialization = false; - bool properties2_ext_enabled = false; - enum class Suitable { yes, partial, no }; - Suitable suitable = Suitable::yes; - friend class PhysicalDeviceSelector; - friend class DeviceBuilder; + bool defer_surface_initialization = false; + bool properties2_ext_enabled = false; + enum class Suitable { yes, partial, no }; + Suitable suitable = Suitable::yes; + friend class PhysicalDeviceSelector; + friend class DeviceBuilder; }; enum class PreferredDeviceType { other = 0, integrated = 1, discrete = 2, virtual_gpu = 3, cpu = 4 }; enum class DeviceSelectionMode { - // return all suitable and partially suitable devices - partially_and_fully_suitable, - // return only physical devices which are fully suitable - only_fully_suitable + // return all suitable and partially suitable devices + partially_and_fully_suitable, + // return only physical devices which are fully suitable + only_fully_suitable }; // Enumerates the physical devices on the system, and based on the added criteria, returns a physical device or list of physical devies // A device is considered suitable if it meets all the 'required' and 'desired' criteria. // A device is considered partially suitable if it meets only the 'required' criteria. class PhysicalDeviceSelector { - public: - // Requires a vkb::Instance to construct, needed to pass instance creation info. - explicit PhysicalDeviceSelector(Instance const& instance); - // Requires a vkb::Instance to construct, needed to pass instance creation info, optionally specify the surface here - explicit PhysicalDeviceSelector(Instance const& instance, VkSurfaceKHR surface); + public: + // Requires a vkb::Instance to construct, needed to pass instance creation info. + explicit PhysicalDeviceSelector(Instance const& instance); + // Requires a vkb::Instance to construct, needed to pass instance creation info, optionally specify the surface here + explicit PhysicalDeviceSelector(Instance const& instance, VkSurfaceKHR surface); - // Return the first device which is suitable - // use the `selection` parameter to configure if partially - Result select(DeviceSelectionMode selection = DeviceSelectionMode::partially_and_fully_suitable) const; + // Return the first device which is suitable + // use the `selection` parameter to configure if partially + Result select(DeviceSelectionMode selection = DeviceSelectionMode::partially_and_fully_suitable) const; - // Return all devices which are considered suitable - intended for applications which want to let the user pick the physical device - Result> select_devices( - DeviceSelectionMode selection = DeviceSelectionMode::partially_and_fully_suitable) const; + // Return all devices which are considered suitable - intended for applications which want to let the user pick the physical device + Result> select_devices( + DeviceSelectionMode selection = DeviceSelectionMode::partially_and_fully_suitable) const; - // Return the names of all devices which are considered suitable - intended for applications which want to let the user pick the physical device - Result> select_device_names( - DeviceSelectionMode selection = DeviceSelectionMode::partially_and_fully_suitable) const; + // Return the names of all devices which are considered suitable - intended for applications which want to let the user pick the physical device + Result> select_device_names( + DeviceSelectionMode selection = DeviceSelectionMode::partially_and_fully_suitable) const; - // Set the surface in which the physical device should render to. - // Be sure to set it if swapchain functionality is to be used. - PhysicalDeviceSelector& set_surface(VkSurfaceKHR surface); + // Set the surface in which the physical device should render to. + // Be sure to set it if swapchain functionality is to be used. + PhysicalDeviceSelector& set_surface(VkSurfaceKHR surface); - // Set the name of the device to select. - PhysicalDeviceSelector& set_name(std::string const& name); - // Set the desired physical device type to select. Defaults to PreferredDeviceType::discrete. - PhysicalDeviceSelector& prefer_gpu_device_type(PreferredDeviceType type = PreferredDeviceType::discrete); - // Allow selection of a gpu device type that isn't the preferred physical device type. Defaults to true. - PhysicalDeviceSelector& allow_any_gpu_device_type(bool allow_any_type = true); + // Set the name of the device to select. + PhysicalDeviceSelector& set_name(std::string const& name); + // Set the desired physical device type to select. Defaults to PreferredDeviceType::discrete. + PhysicalDeviceSelector& prefer_gpu_device_type(PreferredDeviceType type = PreferredDeviceType::discrete); + // Allow selection of a gpu device type that isn't the preferred physical device type. Defaults to true. + PhysicalDeviceSelector& allow_any_gpu_device_type(bool allow_any_type = true); - // Require that a physical device supports presentation. Defaults to true. - PhysicalDeviceSelector& require_present(bool require = true); + // Require that a physical device supports presentation. Defaults to true. + PhysicalDeviceSelector& require_present(bool require = true); - // Require a queue family that supports compute operations but not graphics nor transfer. - PhysicalDeviceSelector& require_dedicated_compute_queue(); - // Require a queue family that supports transfer operations but not graphics nor compute. - PhysicalDeviceSelector& require_dedicated_transfer_queue(); + // Require a queue family that supports compute operations but not graphics nor transfer. + PhysicalDeviceSelector& require_dedicated_compute_queue(); + // Require a queue family that supports transfer operations but not graphics nor compute. + PhysicalDeviceSelector& require_dedicated_transfer_queue(); - // Require a queue family that supports compute operations but not graphics. - PhysicalDeviceSelector& require_separate_compute_queue(); - // Require a queue family that supports transfer operations but not graphics. - PhysicalDeviceSelector& require_separate_transfer_queue(); + // Require a queue family that supports compute operations but not graphics. + PhysicalDeviceSelector& require_separate_compute_queue(); + // Require a queue family that supports transfer operations but not graphics. + PhysicalDeviceSelector& require_separate_transfer_queue(); - // Require a memory heap from VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT with `size` memory available. - PhysicalDeviceSelector& required_device_memory_size(VkDeviceSize size); - // Prefer a memory heap from VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT with `size` memory available. - PhysicalDeviceSelector& desired_device_memory_size(VkDeviceSize size); + // Require a memory heap from VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT with `size` memory available. + PhysicalDeviceSelector& required_device_memory_size(VkDeviceSize size); + // Prefer a memory heap from VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT with `size` memory available. + PhysicalDeviceSelector& desired_device_memory_size(VkDeviceSize size); - // Require a physical device which supports a specific extension. - PhysicalDeviceSelector& add_required_extension(const char* extension); - // Require a physical device which supports a set of extensions. - PhysicalDeviceSelector& add_required_extensions(std::vector extensions); + // Require a physical device which supports a specific extension. + PhysicalDeviceSelector& add_required_extension(const char* extension); + // Require a physical device which supports a set of extensions. + PhysicalDeviceSelector& add_required_extensions(std::vector extensions); - // Prefer a physical device which supports a specific extension. - PhysicalDeviceSelector& add_desired_extension(const char* extension); - // Prefer a physical device which supports a set of extensions. - PhysicalDeviceSelector& add_desired_extensions(std::vector extensions); + // Prefer a physical device which supports a specific extension. + PhysicalDeviceSelector& add_desired_extension(const char* extension); + // Prefer a physical device which supports a set of extensions. + PhysicalDeviceSelector& add_desired_extensions(std::vector extensions); - // Prefer a physical device that supports a (major, minor) version of vulkan. - [[deprecated("Use set_minimum_version + InstanceBuilder::require_api_version.")]] PhysicalDeviceSelector& - set_desired_version(uint32_t major, uint32_t minor); + // Prefer a physical device that supports a (major, minor) version of vulkan. + [[deprecated("Use set_minimum_version + InstanceBuilder::require_api_version.")]] PhysicalDeviceSelector& + set_desired_version(uint32_t major, uint32_t minor); - // 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 that supports a (major, minor) version of vulkan. + PhysicalDeviceSelector& set_minimum_version(uint32_t major, uint32_t minor); - // By default PhysicalDeviceSelector enables the portability subset if available - // This function disables that behavior - PhysicalDeviceSelector& disable_portability_subset(); + // By default PhysicalDeviceSelector enables the portability subset if available + // This function disables that behavior + PhysicalDeviceSelector& disable_portability_subset(); - // Require a physical device which supports a specific set of general/extension features. - // If this function is used, the user should not put their own VkPhysicalDeviceFeatures2 in - // the pNext chain of VkDeviceCreateInfo. - template PhysicalDeviceSelector& add_required_extension_features(T const& features) { - criteria.extended_features_chain.push_back(features); - return *this; - } + // Require a physical device which supports a specific set of general/extension features. + // If this function is used, the user should not put their own VkPhysicalDeviceFeatures2 in + // the pNext chain of VkDeviceCreateInfo. + template PhysicalDeviceSelector& add_required_extension_features(T const& features) { + criteria.extended_features_chain.push_back(features); + return *this; + } - // Require a physical device which supports the features in VkPhysicalDeviceFeatures. - PhysicalDeviceSelector& set_required_features(VkPhysicalDeviceFeatures const& features); + // Require a physical device which supports the features in VkPhysicalDeviceFeatures. + PhysicalDeviceSelector& set_required_features(VkPhysicalDeviceFeatures const& features); #if defined(VKB_VK_API_VERSION_1_2) - // Require a physical device which supports the features in VkPhysicalDeviceVulkan11Features. - // Must have vulkan version 1.2 - This is due to the VkPhysicalDeviceVulkan11Features struct being added in 1.2, not 1.1 - PhysicalDeviceSelector& set_required_features_11(VkPhysicalDeviceVulkan11Features features_11); - // Require a physical device which supports the features in VkPhysicalDeviceVulkan12Features. - // Must have vulkan version 1.2 - PhysicalDeviceSelector& set_required_features_12(VkPhysicalDeviceVulkan12Features features_12); + // Require a physical device which supports the features in VkPhysicalDeviceVulkan11Features. + // Must have vulkan version 1.2 - This is due to the VkPhysicalDeviceVulkan11Features struct being added in 1.2, not 1.1 + PhysicalDeviceSelector& set_required_features_11(VkPhysicalDeviceVulkan11Features features_11); + // Require a physical device which supports the features in VkPhysicalDeviceVulkan12Features. + // Must have vulkan version 1.2 + PhysicalDeviceSelector& set_required_features_12(VkPhysicalDeviceVulkan12Features features_12); #endif #if defined(VKB_VK_API_VERSION_1_3) - // Require a physical device which supports the features in VkPhysicalDeviceVulkan13Features. - // Must have vulkan version 1.3 - PhysicalDeviceSelector& set_required_features_13(VkPhysicalDeviceVulkan13Features features_13); + // Require a physical device which supports the features in VkPhysicalDeviceVulkan13Features. + // Must have vulkan version 1.3 + PhysicalDeviceSelector& set_required_features_13(VkPhysicalDeviceVulkan13Features features_13); #endif - // Used when surface creation happens after physical device selection. - // Warning: This disables checking if the physical device supports a given surface. - PhysicalDeviceSelector& defer_surface_initialization(); + // Used when surface creation happens after physical device selection. + // Warning: This disables checking if the physical device supports a given surface. + PhysicalDeviceSelector& defer_surface_initialization(); - // Ignore all criteria and choose the first physical device that is available. - // Only use when: The first gpu in the list may be set by global user preferences and an application may wish to respect it. - PhysicalDeviceSelector& select_first_device_unconditionally(bool unconditionally = true); + // Ignore all criteria and choose the first physical device that is available. + // Only use when: The first gpu in the list may be set by global user preferences and an application may wish to respect it. + PhysicalDeviceSelector& select_first_device_unconditionally(bool unconditionally = true); - private: - struct InstanceInfo { - VkInstance instance = VK_NULL_HANDLE; - VkSurfaceKHR surface = VK_NULL_HANDLE; - uint32_t version = VKB_VK_API_VERSION_1_0; - bool headless = false; - bool properties2_ext_enabled = false; - } instance_info; + private: + struct InstanceInfo { + VkInstance instance = VK_NULL_HANDLE; + VkSurfaceKHR surface = VK_NULL_HANDLE; + uint32_t version = VKB_VK_API_VERSION_1_0; + bool headless = false; + bool properties2_ext_enabled = false; + } instance_info; - // We copy the extension features stored in the selector criteria under the prose of a - // "template" to ensure that after fetching everything is compared 1:1 during a match. + // We copy the extension features stored in the selector criteria under the prose of a + // "template" to ensure that after fetching everything is compared 1:1 during a match. - struct SelectionCriteria { - std::string name; - PreferredDeviceType preferred_type = PreferredDeviceType::discrete; - bool allow_any_type = true; - bool require_present = true; - bool require_dedicated_transfer_queue = false; - bool require_dedicated_compute_queue = false; - bool require_separate_transfer_queue = false; - bool require_separate_compute_queue = false; - VkDeviceSize required_mem_size = 0; - VkDeviceSize desired_mem_size = 0; + struct SelectionCriteria { + std::string name; + PreferredDeviceType preferred_type = PreferredDeviceType::discrete; + bool allow_any_type = true; + bool require_present = true; + bool require_dedicated_transfer_queue = false; + bool require_dedicated_compute_queue = false; + bool require_separate_transfer_queue = false; + bool require_separate_compute_queue = false; + VkDeviceSize required_mem_size = 0; + VkDeviceSize desired_mem_size = 0; - std::vector required_extensions; - std::vector desired_extensions; + std::vector required_extensions; + std::vector desired_extensions; - uint32_t required_version = VKB_VK_API_VERSION_1_0; - uint32_t desired_version = VKB_VK_API_VERSION_1_0; + uint32_t required_version = VKB_VK_API_VERSION_1_0; + uint32_t desired_version = VKB_VK_API_VERSION_1_0; - VkPhysicalDeviceFeatures required_features{}; - VkPhysicalDeviceFeatures2 required_features2{}; + VkPhysicalDeviceFeatures required_features{}; + VkPhysicalDeviceFeatures2 required_features2{}; - std::vector extended_features_chain; - bool defer_surface_initialization = false; - bool use_first_gpu_unconditionally = false; - bool enable_portability_subset = true; - } criteria; + std::vector extended_features_chain; + bool defer_surface_initialization = false; + bool use_first_gpu_unconditionally = false; + bool enable_portability_subset = true; + } criteria; - PhysicalDevice populate_device_details(VkPhysicalDevice phys_device, - std::vector const& src_extended_features_chain) const; + PhysicalDevice populate_device_details(VkPhysicalDevice phys_device, + std::vector const& src_extended_features_chain) const; - PhysicalDevice::Suitable is_device_suitable(PhysicalDevice const& phys_device) const; + PhysicalDevice::Suitable is_device_suitable(PhysicalDevice const& phys_device) const; - Result> select_impl(DeviceSelectionMode selection) const; + Result> select_impl(DeviceSelectionMode selection) const; }; // ---- Queue ---- // @@ -682,252 +682,252 @@ const uint32_t QUEUE_INDEX_MAX_VALUE = 65536; // ---- Device ---- // struct Device { - VkDevice device = VK_NULL_HANDLE; - PhysicalDevice physical_device; - VkSurfaceKHR surface = VK_NULL_HANDLE; - std::vector queue_families; - VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE; - PFN_vkGetDeviceProcAddr fp_vkGetDeviceProcAddr = nullptr; - uint32_t instance_version = VKB_VK_API_VERSION_1_0; + VkDevice device = VK_NULL_HANDLE; + PhysicalDevice physical_device; + VkSurfaceKHR surface = VK_NULL_HANDLE; + std::vector queue_families; + VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE; + PFN_vkGetDeviceProcAddr fp_vkGetDeviceProcAddr = nullptr; + uint32_t instance_version = VKB_VK_API_VERSION_1_0; - Result get_queue_index(QueueType type) const; - // Only a compute or transfer queue type is valid. All other queue types do not support a 'dedicated' queue index - Result get_dedicated_queue_index(QueueType type) const; + Result get_queue_index(QueueType type) const; + // Only a compute or transfer queue type is valid. All other queue types do not support a 'dedicated' queue index + Result get_dedicated_queue_index(QueueType type) const; - Result get_queue(QueueType type) const; - // Only a compute or transfer queue type is valid. All other queue types do not support a 'dedicated' queue - Result get_dedicated_queue(QueueType type) const; + Result get_queue(QueueType type) const; + // Only a compute or transfer queue type is valid. All other queue types do not support a 'dedicated' queue + Result get_dedicated_queue(QueueType type) const; - // Return a loaded dispatch table - DispatchTable make_table() const; + // Return a loaded dispatch table + DispatchTable make_table() const; - // A conversion function which allows this Device to be used - // in places where VkDevice would have been used. - operator VkDevice() const; + // A conversion function which allows this Device to be used + // in places where VkDevice would have been used. + operator VkDevice() const; - private: - struct { - PFN_vkGetDeviceQueue fp_vkGetDeviceQueue = nullptr; - PFN_vkDestroyDevice fp_vkDestroyDevice = nullptr; - } internal_table; - friend class DeviceBuilder; - friend void destroy_device(Device device); + private: + struct { + PFN_vkGetDeviceQueue fp_vkGetDeviceQueue = nullptr; + PFN_vkDestroyDevice fp_vkDestroyDevice = nullptr; + } internal_table; + friend class DeviceBuilder; + friend void destroy_device(Device device); }; // For advanced device queue setup struct CustomQueueDescription { - explicit CustomQueueDescription(uint32_t index, uint32_t count, std::vector priorities); - uint32_t index = 0; - uint32_t count = 0; - std::vector priorities; + explicit CustomQueueDescription(uint32_t index, uint32_t count, std::vector priorities); + uint32_t index = 0; + uint32_t count = 0; + std::vector priorities; }; void destroy_device(Device device); class DeviceBuilder { - public: - // Any features and extensions that are requested/required in PhysicalDeviceSelector are automatically enabled. - explicit DeviceBuilder(PhysicalDevice physical_device); + public: + // Any features and extensions that are requested/required in PhysicalDeviceSelector are automatically enabled. + explicit DeviceBuilder(PhysicalDevice physical_device); - Result build() const; + Result build() const; - // For Advanced Users: specify the exact list of VkDeviceQueueCreateInfo's needed for the application. - // If a custom queue setup is provided, getting the queues and queue indexes is up to the application. - DeviceBuilder& custom_queue_setup(std::vector queue_descriptions); + // For Advanced Users: specify the exact list of VkDeviceQueueCreateInfo's needed for the application. + // If a custom queue setup is provided, getting the queues and queue indexes is up to the application. + DeviceBuilder& custom_queue_setup(std::vector queue_descriptions); - // Add a structure to the pNext chain of VkDeviceCreateInfo. - // The structure must be valid when DeviceBuilder::build() is called. - template DeviceBuilder& add_pNext(T* structure) { - info.pNext_chain.push_back(reinterpret_cast(structure)); - return *this; - } + // Add a structure to the pNext chain of VkDeviceCreateInfo. + // The structure must be valid when DeviceBuilder::build() is called. + template DeviceBuilder& add_pNext(T* structure) { + info.pNext_chain.push_back(reinterpret_cast(structure)); + return *this; + } - // Provide custom allocation callbacks. - DeviceBuilder& set_allocation_callbacks(VkAllocationCallbacks* callbacks); + // Provide custom allocation callbacks. + DeviceBuilder& set_allocation_callbacks(VkAllocationCallbacks* callbacks); - private: - PhysicalDevice physical_device; - struct DeviceInfo { - VkDeviceCreateFlags flags = static_cast(0); - std::vector pNext_chain; - std::vector queue_descriptions; - VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE; - } info; + private: + PhysicalDevice physical_device; + struct DeviceInfo { + VkDeviceCreateFlags flags = static_cast(0); + std::vector pNext_chain; + std::vector queue_descriptions; + VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE; + } info; }; // ---- Swapchain ---- // struct Swapchain { - VkDevice device = VK_NULL_HANDLE; - VkSwapchainKHR swapchain = VK_NULL_HANDLE; - uint32_t image_count = 0; - VkFormat image_format = VK_FORMAT_UNDEFINED; // The image format actually used when creating the swapchain. - VkColorSpaceKHR color_space = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; // The color space actually used when creating the swapchain. - VkImageUsageFlags image_usage_flags = 0; - VkExtent2D extent = { 0, 0 }; - // The value of minImageCount actually used when creating the swapchain; note that the presentation engine is always free to create more images than that. - uint32_t requested_min_image_count = 0; - VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR; // The present mode actually used when creating the swapchain. - uint32_t instance_version = VKB_VK_API_VERSION_1_0; - VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE; + VkDevice device = VK_NULL_HANDLE; + VkSwapchainKHR swapchain = VK_NULL_HANDLE; + uint32_t image_count = 0; + VkFormat image_format = VK_FORMAT_UNDEFINED; // The image format actually used when creating the swapchain. + VkColorSpaceKHR color_space = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; // The color space actually used when creating the swapchain. + VkImageUsageFlags image_usage_flags = 0; + VkExtent2D extent = { 0, 0 }; + // The value of minImageCount actually used when creating the swapchain; note that the presentation engine is always free to create more images than that. + uint32_t requested_min_image_count = 0; + VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR; // The present mode actually used when creating the swapchain. + uint32_t instance_version = VKB_VK_API_VERSION_1_0; + VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE; - // Returns a vector of VkImage handles to the swapchain. - Result> get_images(); + // Returns a vector of VkImage handles to the swapchain. + Result> get_images(); - // Returns a vector of VkImageView's to the VkImage's of the swapchain. - // VkImageViews must be destroyed. The pNext chain must be a nullptr or a valid - // structure. - Result> get_image_views(); - Result> get_image_views(const void* pNext); - void destroy_image_views(std::vector const& image_views); + // Returns a vector of VkImageView's to the VkImage's of the swapchain. + // VkImageViews must be destroyed. The pNext chain must be a nullptr or a valid + // structure. + Result> get_image_views(); + Result> get_image_views(const void* pNext); + void destroy_image_views(std::vector const& image_views); - // A conversion function which allows this Swapchain to be used - // in places where VkSwapchainKHR would have been used. - operator VkSwapchainKHR() const; + // A conversion function which allows this Swapchain to be used + // in places where VkSwapchainKHR would have been used. + operator VkSwapchainKHR() const; - private: - struct { - PFN_vkGetSwapchainImagesKHR fp_vkGetSwapchainImagesKHR = nullptr; - PFN_vkCreateImageView fp_vkCreateImageView = nullptr; - PFN_vkDestroyImageView fp_vkDestroyImageView = nullptr; - PFN_vkDestroySwapchainKHR fp_vkDestroySwapchainKHR = nullptr; - } internal_table; - friend class SwapchainBuilder; - friend void destroy_swapchain(Swapchain const& swapchain); + private: + struct { + PFN_vkGetSwapchainImagesKHR fp_vkGetSwapchainImagesKHR = nullptr; + PFN_vkCreateImageView fp_vkCreateImageView = nullptr; + PFN_vkDestroyImageView fp_vkDestroyImageView = nullptr; + PFN_vkDestroySwapchainKHR fp_vkDestroySwapchainKHR = nullptr; + } internal_table; + friend class SwapchainBuilder; + friend void destroy_swapchain(Swapchain const& swapchain); }; void destroy_swapchain(Swapchain const& swapchain); class SwapchainBuilder { - public: - // Construct a SwapchainBuilder with a `vkb::Device` - explicit SwapchainBuilder(Device const& device); - // Construct a SwapchainBuilder with a specific VkSurfaceKHR handle and `vkb::Device` - explicit SwapchainBuilder(Device const& device, VkSurfaceKHR const surface); - // Construct a SwapchainBuilder with Vulkan handles for the physical device, device, and surface - // Optionally can provide the uint32_t indices for the graphics and present queue - // Note: The constructor will query the graphics & present queue if the indices are not provided - explicit SwapchainBuilder(VkPhysicalDevice const physical_device, - VkDevice const device, - VkSurfaceKHR const surface, - uint32_t graphics_queue_index = detail::QUEUE_INDEX_MAX_VALUE, - uint32_t present_queue_index = detail::QUEUE_INDEX_MAX_VALUE); + public: + // Construct a SwapchainBuilder with a `vkb::Device` + explicit SwapchainBuilder(Device const& device); + // Construct a SwapchainBuilder with a specific VkSurfaceKHR handle and `vkb::Device` + explicit SwapchainBuilder(Device const& device, VkSurfaceKHR const surface); + // Construct a SwapchainBuilder with Vulkan handles for the physical device, device, and surface + // Optionally can provide the uint32_t indices for the graphics and present queue + // Note: The constructor will query the graphics & present queue if the indices are not provided + explicit SwapchainBuilder(VkPhysicalDevice const physical_device, + VkDevice const device, + VkSurfaceKHR const surface, + uint32_t graphics_queue_index = detail::QUEUE_INDEX_MAX_VALUE, + uint32_t present_queue_index = detail::QUEUE_INDEX_MAX_VALUE); - Result build() const; + Result build() const; - // Set the oldSwapchain member of VkSwapchainCreateInfoKHR. - // For use in rebuilding a swapchain. - SwapchainBuilder& set_old_swapchain(VkSwapchainKHR old_swapchain); - SwapchainBuilder& set_old_swapchain(Swapchain const& swapchain); + // Set the oldSwapchain member of VkSwapchainCreateInfoKHR. + // For use in rebuilding a swapchain. + SwapchainBuilder& set_old_swapchain(VkSwapchainKHR old_swapchain); + SwapchainBuilder& set_old_swapchain(Swapchain const& swapchain); - // Desired size of the swapchain. By default, the swapchain will use the size - // of the window being drawn to. - SwapchainBuilder& set_desired_extent(uint32_t width, uint32_t height); + // Desired size of the swapchain. By default, the swapchain will use the size + // of the window being drawn to. + SwapchainBuilder& set_desired_extent(uint32_t width, uint32_t height); - // When determining the surface format, make this the first to be used if supported. - SwapchainBuilder& set_desired_format(VkSurfaceFormatKHR format); - // Add this swapchain format to the end of the list of formats selected from. - SwapchainBuilder& add_fallback_format(VkSurfaceFormatKHR format); - // Use the default swapchain formats. This is done if no formats are provided. - // Default surface format is {VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR} - SwapchainBuilder& use_default_format_selection(); + // When determining the surface format, make this the first to be used if supported. + SwapchainBuilder& set_desired_format(VkSurfaceFormatKHR format); + // Add this swapchain format to the end of the list of formats selected from. + SwapchainBuilder& add_fallback_format(VkSurfaceFormatKHR format); + // Use the default swapchain formats. This is done if no formats are provided. + // Default surface format is {VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR} + SwapchainBuilder& use_default_format_selection(); - // When determining the present mode, make this the first to be used if supported. - SwapchainBuilder& set_desired_present_mode(VkPresentModeKHR present_mode); - // Add this present mode to the end of the list of present modes selected from. - SwapchainBuilder& add_fallback_present_mode(VkPresentModeKHR present_mode); - // Use the default presentation mode. This is done if no present modes are provided. - // Default present modes: VK_PRESENT_MODE_MAILBOX_KHR with fallback VK_PRESENT_MODE_FIFO_KHR - SwapchainBuilder& use_default_present_mode_selection(); + // When determining the present mode, make this the first to be used if supported. + SwapchainBuilder& set_desired_present_mode(VkPresentModeKHR present_mode); + // Add this present mode to the end of the list of present modes selected from. + SwapchainBuilder& add_fallback_present_mode(VkPresentModeKHR present_mode); + // Use the default presentation mode. This is done if no present modes are provided. + // Default present modes: VK_PRESENT_MODE_MAILBOX_KHR with fallback VK_PRESENT_MODE_FIFO_KHR + SwapchainBuilder& use_default_present_mode_selection(); - // Set the bitmask of the image usage for acquired swapchain images. - // If the surface capabilities cannot allow it, building the swapchain will result in the `SwapchainError::required_usage_not_supported` error. - SwapchainBuilder& set_image_usage_flags(VkImageUsageFlags usage_flags); - // Add a image usage to the bitmask for acquired swapchain images. - SwapchainBuilder& add_image_usage_flags(VkImageUsageFlags usage_flags); - // Use the default image usage bitmask values. This is the default if no image usages - // are provided. The default is VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT - SwapchainBuilder& use_default_image_usage_flags(); + // Set the bitmask of the image usage for acquired swapchain images. + // If the surface capabilities cannot allow it, building the swapchain will result in the `SwapchainError::required_usage_not_supported` error. + SwapchainBuilder& set_image_usage_flags(VkImageUsageFlags usage_flags); + // Add a image usage to the bitmask for acquired swapchain images. + SwapchainBuilder& add_image_usage_flags(VkImageUsageFlags usage_flags); + // Use the default image usage bitmask values. This is the default if no image usages + // are provided. The default is VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT + SwapchainBuilder& use_default_image_usage_flags(); - // Set the number of views in for multiview/stereo surface - SwapchainBuilder& set_image_array_layer_count(uint32_t array_layer_count); + // Set the number of views in for multiview/stereo surface + SwapchainBuilder& set_image_array_layer_count(uint32_t array_layer_count); - // Convenient named constants for passing to set_desired_min_image_count(). - // Note that it is not an `enum class`, so its constants can be passed as an integer value without casting - // In other words, these might as well be `static const int`, but they benefit from being grouped together this way. - enum BufferMode { - SINGLE_BUFFERING = 1, - DOUBLE_BUFFERING = 2, - TRIPLE_BUFFERING = 3, - }; + // Convenient named constants for passing to set_desired_min_image_count(). + // Note that it is not an `enum class`, so its constants can be passed as an integer value without casting + // In other words, these might as well be `static const int`, but they benefit from being grouped together this way. + enum BufferMode { + SINGLE_BUFFERING = 1, + DOUBLE_BUFFERING = 2, + TRIPLE_BUFFERING = 3, + }; - // Sets the desired minimum image count for the swapchain. - // Note that the presentation engine is always free to create more images than requested. - // You may pass one of the values specified in the BufferMode enum, or any integer value. - // For instance, if you pass DOUBLE_BUFFERING, the presentation engine is allowed to give you a double buffering setup, triple buffering, or more. This is up to the drivers. - SwapchainBuilder& set_desired_min_image_count(uint32_t min_image_count); + // Sets the desired minimum image count for the swapchain. + // Note that the presentation engine is always free to create more images than requested. + // You may pass one of the values specified in the BufferMode enum, or any integer value. + // For instance, if you pass DOUBLE_BUFFERING, the presentation engine is allowed to give you a double buffering setup, triple buffering, or more. This is up to the drivers. + SwapchainBuilder& set_desired_min_image_count(uint32_t min_image_count); - // Sets a required minimum image count for the swapchain. - // If the surface capabilities cannot allow it, building the swapchain will result in the `SwapchainError::required_min_image_count_too_low` error. - // Otherwise, the same observations from set_desired_min_image_count() apply. - // A value of 0 is specially interpreted as meaning "no requirement", and is the behavior by default. - SwapchainBuilder& set_required_min_image_count(uint32_t required_min_image_count); + // Sets a required minimum image count for the swapchain. + // If the surface capabilities cannot allow it, building the swapchain will result in the `SwapchainError::required_min_image_count_too_low` error. + // Otherwise, the same observations from set_desired_min_image_count() apply. + // A value of 0 is specially interpreted as meaning "no requirement", and is the behavior by default. + SwapchainBuilder& set_required_min_image_count(uint32_t required_min_image_count); - // Set whether the Vulkan implementation is allowed to discard rendering operations that - // affect regions of the surface that are not visible. Default is true. - // Note: Applications should use the default of true if they do not expect to read back the content - // of presentable images before presenting them or after reacquiring them, and if their fragment - // shaders do not have any side effects that require them to run for all pixels in the presentable image. - SwapchainBuilder& set_clipped(bool clipped = true); + // Set whether the Vulkan implementation is allowed to discard rendering operations that + // affect regions of the surface that are not visible. Default is true. + // Note: Applications should use the default of true if they do not expect to read back the content + // of presentable images before presenting them or after reacquiring them, and if their fragment + // shaders do not have any side effects that require them to run for all pixels in the presentable image. + SwapchainBuilder& set_clipped(bool clipped = true); - // Set the VkSwapchainCreateFlagBitsKHR. - SwapchainBuilder& set_create_flags(VkSwapchainCreateFlagBitsKHR create_flags); - // Set the transform to be applied, like a 90 degree rotation. Default is no transform. - SwapchainBuilder& set_pre_transform_flags(VkSurfaceTransformFlagBitsKHR pre_transform_flags); - // Set the alpha channel to be used with other windows in on the system. Default is VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR. - SwapchainBuilder& set_composite_alpha_flags(VkCompositeAlphaFlagBitsKHR composite_alpha_flags); + // Set the VkSwapchainCreateFlagBitsKHR. + SwapchainBuilder& set_create_flags(VkSwapchainCreateFlagBitsKHR create_flags); + // Set the transform to be applied, like a 90 degree rotation. Default is no transform. + SwapchainBuilder& set_pre_transform_flags(VkSurfaceTransformFlagBitsKHR pre_transform_flags); + // Set the alpha channel to be used with other windows in on the system. Default is VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR. + SwapchainBuilder& set_composite_alpha_flags(VkCompositeAlphaFlagBitsKHR composite_alpha_flags); - // Add a structure to the pNext chain of VkSwapchainCreateInfoKHR. - // The structure must be valid when SwapchainBuilder::build() is called. - template SwapchainBuilder& add_pNext(T* structure) { - info.pNext_chain.push_back(reinterpret_cast(structure)); - return *this; - } + // Add a structure to the pNext chain of VkSwapchainCreateInfoKHR. + // The structure must be valid when SwapchainBuilder::build() is called. + template SwapchainBuilder& add_pNext(T* structure) { + info.pNext_chain.push_back(reinterpret_cast(structure)); + return *this; + } - // Provide custom allocation callbacks. - SwapchainBuilder& set_allocation_callbacks(VkAllocationCallbacks* callbacks); + // Provide custom allocation callbacks. + SwapchainBuilder& set_allocation_callbacks(VkAllocationCallbacks* callbacks); - private: - void add_desired_formats(std::vector& formats) const; - void add_desired_present_modes(std::vector& modes) const; + private: + void add_desired_formats(std::vector& formats) const; + void add_desired_present_modes(std::vector& modes) const; - struct SwapchainInfo { - VkPhysicalDevice physical_device = VK_NULL_HANDLE; - VkDevice device = VK_NULL_HANDLE; - std::vector pNext_chain; - VkSwapchainCreateFlagBitsKHR create_flags = static_cast(0); - VkSurfaceKHR surface = VK_NULL_HANDLE; - std::vector desired_formats; - uint32_t instance_version = VKB_VK_API_VERSION_1_0; - uint32_t desired_width = 256; - uint32_t desired_height = 256; - uint32_t array_layer_count = 1; - uint32_t min_image_count = 0; - uint32_t required_min_image_count = 0; - VkImageUsageFlags image_usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - uint32_t graphics_queue_index = 0; - uint32_t present_queue_index = 0; - VkSurfaceTransformFlagBitsKHR pre_transform = static_cast(0); + struct SwapchainInfo { + VkPhysicalDevice physical_device = VK_NULL_HANDLE; + VkDevice device = VK_NULL_HANDLE; + std::vector pNext_chain; + VkSwapchainCreateFlagBitsKHR create_flags = static_cast(0); + VkSurfaceKHR surface = VK_NULL_HANDLE; + std::vector desired_formats; + uint32_t instance_version = VKB_VK_API_VERSION_1_0; + uint32_t desired_width = 256; + uint32_t desired_height = 256; + uint32_t array_layer_count = 1; + uint32_t min_image_count = 0; + uint32_t required_min_image_count = 0; + VkImageUsageFlags image_usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + uint32_t graphics_queue_index = 0; + uint32_t present_queue_index = 0; + VkSurfaceTransformFlagBitsKHR pre_transform = static_cast(0); #if defined(__ANDROID__) - VkCompositeAlphaFlagBitsKHR composite_alpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; + VkCompositeAlphaFlagBitsKHR composite_alpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; #else - VkCompositeAlphaFlagBitsKHR composite_alpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + VkCompositeAlphaFlagBitsKHR composite_alpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; #endif - std::vector desired_present_modes; - bool clipped = true; - VkSwapchainKHR old_swapchain = VK_NULL_HANDLE; - VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE; - } info; + std::vector desired_present_modes; + bool clipped = true; + VkSwapchainKHR old_swapchain = VK_NULL_HANDLE; + VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE; + } info; }; } // namespace vkb