aboutsummaryrefslogtreecommitdiffstats
path: root/api-test/vk-device.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'api-test/vk-device.cpp')
-rw-r--r--api-test/vk-device.cpp519
1 files changed, 519 insertions, 0 deletions
diff --git a/api-test/vk-device.cpp b/api-test/vk-device.cpp
new file mode 100644
index 0000000..4b7c0d0
--- /dev/null
+++ b/api-test/vk-device.cpp
@@ -0,0 +1,519 @@
+#include "vk-device.hpp"
+#include "color.hpp"
+
+#include <cassert>
+#include <iostream>
+#include <thread>
+#include <vector>
+
+#define VMA_IMPLEMENTATION
+#include <vk_mem_alloc.h>
+
+#include "vulkan-loader.hpp"
+#include "window.hpp"
+
+#ifdef _DEBUG
+#define VKCHECK(result) assert(result == VK_SUCCESS);
+#else
+#define VKCHECK(result) result;
+#endif
+
+VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
+ VkDebugUtilsMessageTypeFlagsEXT type,
+ const VkDebugUtilsMessengerCallbackDataEXT* data,
+ void*) {
+ const char* severity_cstr = nullptr;
+ switch (severity) {
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
+ severity_cstr = "VERBOSE";
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
+ severity_cstr = "INFO";
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
+ severity_cstr = "WARNING";
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
+ severity_cstr = "ERROR";
+ break;
+ default:
+ break;
+ }
+
+ const char* type_cstr = nullptr;
+ switch (type) {
+ case VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT:
+ type_cstr = "GENERAL";
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT:
+ type_cstr = "VALIDATION";
+ break;
+ case VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT:
+ type_cstr = "PERFORMANCE";
+ break;
+ default:
+ break;
+ }
+
+ std::cerr << "[" << severity_cstr << "_" << type_cstr << "]: " << data->pMessage << std::endl;
+ return VK_FALSE;
+}
+
+vkdevice::vkdevice(const window& window)
+ : queues{
+ {
+ .usages = VK_QUEUE_GRAPHICS_BIT,
+ },
+ // { .usages = VK_QUEUE_TRANSFER_BIT, },
+ } {
+ load_vulkan();
+ create_instance();
+
+#ifdef _DEBUG
+ create_debug_layer_callback();
+#endif // _DEBUG
+
+ create_device();
+
+ create_memory_allocator();
+
+ create_surface(window);
+
+ create_swapchain();
+}
+
+handle<device_texture> vkdevice::create_texture(const texture_desc& desc) {
+ device_texture device_texture = {};
+ device_texture.desc = desc;
+
+ assert(desc.mips <= texture_desc::max_mips);
+
+ VkImageCreateInfo create_info = {};
+ create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ create_info.pNext = nullptr;
+ create_info.flags = 0U;
+ create_info.imageType = desc.type;
+ create_info.format = desc.format;
+ create_info.extent = {
+ .width = desc.width,
+ .height = desc.height,
+ .depth = desc.depth
+ };
+ create_info.mipLevels = desc.mips;
+ create_info.arrayLayers = 1;
+ create_info.samples = VK_SAMPLE_COUNT_1_BIT;
+ create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
+ create_info.usage = desc.usages;
+ create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ create_info.queueFamilyIndexCount = 0;
+ create_info.pQueueFamilyIndices = nullptr;
+ create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+
+ VmaAllocationCreateInfo alloc_create_info = {};
+ alloc_create_info.flags = 0U;
+ alloc_create_info.usage = VMA_MEMORY_USAGE_GPU_ONLY;
+ alloc_create_info.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ alloc_create_info.preferredFlags = 0U;
+ alloc_create_info.memoryTypeBits = 0U;
+ alloc_create_info.pool = nullptr;
+ alloc_create_info.pUserData = nullptr;
+
+ VKCHECK(vmaCreateImage(gpu_allocator, &create_info, &alloc_create_info, &device_texture.handle, &device_texture.alloc, nullptr))
+
+ if ((desc.usages & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0U ||
+ (desc.usages & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0U) {
+ create_views(device_texture);
+ }
+
+ return { textures.add(device_texture) };
+}
+
+handle<device_buffer> vkdevice::create_buffer(const buffer_desc& desc) {
+ device_buffer device_buffer = {};
+ device_buffer.desc = desc;
+
+ VkBufferCreateInfo create_info = {};
+ create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ create_info.pNext = nullptr;
+ create_info.flags = 0U;
+ create_info.size = desc.size;
+ create_info.usage = desc.usages;
+ create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ create_info.queueFamilyIndexCount = 0;
+ create_info.pQueueFamilyIndices = nullptr;
+
+ VmaAllocatorCreateFlags alloc_create_flags =
+ desc.memory_usage != VMA_MEMORY_USAGE_GPU_ONLY ?
+ VMA_ALLOCATION_CREATE_MAPPED_BIT : 0U;
+
+ VmaAllocationCreateInfo alloc_create_info = {};
+ alloc_create_info.flags = alloc_create_flags;
+ alloc_create_info.usage = static_cast<VmaMemoryUsage>(desc.memory_usage);
+ alloc_create_info.requiredFlags = desc.memory_properties;
+ alloc_create_info.preferredFlags = 0U;
+ alloc_create_info.memoryTypeBits = 0U;
+ alloc_create_info.pool = nullptr;
+ alloc_create_info.pUserData = nullptr;
+
+ VmaAllocationInfo alloc_info = {};
+
+ VKCHECK(vmaCreateBuffer(gpu_allocator, &create_info, &alloc_create_info, &device_buffer.handle, &device_buffer.alloc, &alloc_info))
+
+ device_buffer.mapped_ptr = alloc_info.pMappedData;
+
+ return { buffers.add(device_buffer) };
+}
+
+void vkdevice::submit(std::span<graphics_command_buffer> command_buffers) {
+ VkSubmitInfo submit_info = {};
+ submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submit_info.pNext = nullptr;
+ submit_info.waitSemaphoreCount;
+ submit_info.pWaitSemaphores;
+ submit_info.pWaitDstStageMask;
+ submit_info.commandBufferCount;
+ submit_info.pCommandBuffers;
+ submit_info.signalSemaphoreCount;
+ submit_info.pSignalSemaphores;
+
+ vkQueueSubmit()
+}
+
+
+// private
+
+void vkdevice::create_views(device_texture& texture) {
+ VkImageAspectFlags aspect_mask = ((texture.desc.usages & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0U)
+ ? VK_IMAGE_ASPECT_COLOR_BIT
+ : VK_IMAGE_ASPECT_DEPTH_BIT;
+ VkImageViewCreateInfo create_info = {};
+ create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ create_info.pNext = nullptr;
+ create_info.flags = 0U;
+ create_info.image = texture.handle;
+ create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ create_info.format = texture.desc.format;
+ create_info.components = {
+ .r = VK_COMPONENT_SWIZZLE_R,
+ .g = VK_COMPONENT_SWIZZLE_G,
+ .b = VK_COMPONENT_SWIZZLE_B,
+ .a = VK_COMPONENT_SWIZZLE_A,
+ };
+ create_info.subresourceRange = {
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, // TODO: Choose either color or depth based on format ?
+ .baseMipLevel = 0,
+ .levelCount = 1,
+ .baseArrayLayer = 0,
+ .layerCount = 1,
+ };
+
+ for (auto mip_index{ 0 }; mip_index < texture.desc.mips; mip_index++) {
+ create_info.subresourceRange.baseMipLevel = mip_index;
+ VKCHECK(vkCreateImageView(device, &create_info, nullptr, &texture.mips_views[mip_index]))
+ }
+
+ create_info.subresourceRange.baseMipLevel = 0;
+ create_info.subresourceRange.levelCount = texture.desc.mips;
+ VKCHECK(vkCreateImageView(device, &create_info, nullptr, &texture.whole_view))
+}
+
+void vkdevice::create_surface(const window& window) {
+ VkWin32SurfaceCreateInfoKHR create_info = {};
+ create_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
+ create_info.pNext = nullptr;
+ create_info.flags = 0U;
+ create_info.hinstance = GetModuleHandle(nullptr);
+ create_info.hwnd = window.handle;
+
+ VKCHECK(vkCreateWin32SurfaceKHR(instance, &create_info, nullptr, &surface))
+}
+
+void vkdevice::create_swapchain() {
+ VkBool32 supported = VK_FALSE;
+ for (auto index{ 0U }; index < QueueTypes::MAX; index++) {
+ auto& queue = queues[index];
+ VKCHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, queue.index, surface, &supported))
+
+ assert(supported);
+ }
+
+ VkSurfaceCapabilitiesKHR surface_capabilities = {};
+ VKCHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &surface_capabilities))
+
+ VkExtent2D extent = surface_capabilities.currentExtent;
+
+ if (extent.width < surface_capabilities.minImageExtent.width) {
+ extent.width = surface_capabilities.minImageExtent.width;
+ } else if (extent.width > surface_capabilities.maxImageExtent.width) {
+ extent.width = surface_capabilities.maxImageExtent.width;
+ }
+
+ if (extent.height < surface_capabilities.minImageExtent.height) {
+ extent.height = surface_capabilities.minImageExtent.height;
+ } else if (extent.height > surface_capabilities.maxImageExtent.height) {
+ extent.height = surface_capabilities.maxImageExtent.height;
+ }
+
+ auto supported_formats_count = 0U;
+ VKCHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &supported_formats_count, VK_NULL_HANDLE))
+
+ std::vector<VkSurfaceFormatKHR> supported_formats{ supported_formats_count };
+ VKCHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &supported_formats_count, supported_formats.data()))
+
+
+ auto supported_present_modes_count = 0U;
+ VKCHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &supported_present_modes_count, VK_NULL_HANDLE))
+
+ std::vector<VkPresentModeKHR> supported_present_modes{ supported_present_modes_count };
+
+ VKCHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &supported_present_modes_count, supported_present_modes.data()))
+
+ VkSwapchainCreateInfoKHR create_info = {};
+ create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+ create_info.pNext = nullptr;
+ create_info.flags = 0U;
+ create_info.surface = surface;
+ create_info.minImageCount = surface_capabilities.minImageCount;
+ create_info.imageFormat = supported_formats[0].format;
+ create_info.imageColorSpace = supported_formats[0].colorSpace;
+ create_info.imageExtent = extent;
+ create_info.imageArrayLayers = 1U;
+ create_info.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ create_info.queueFamilyIndexCount = 0U;
+ create_info.pQueueFamilyIndices = nullptr;
+ create_info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+ create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+ create_info.presentMode = supported_present_modes[0];
+ create_info.clipped = VK_TRUE;
+ create_info.oldSwapchain = nullptr;
+
+ VKCHECK(vkCreateSwapchainKHR(device, &create_info, nullptr, &swapchain))
+}
+
+// ----------------- vkadapter -----------------
+
+void vkdevice::create_instance() {
+ VkApplicationInfo app_info = {};
+ app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+ app_info.pApplicationName = "path-tracer";
+ app_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
+ app_info.pEngineName = "gpu-path-tracer";
+ app_info.engineVersion = VK_MAKE_VERSION(1, 0, 0);
+ app_info.apiVersion = VK_API_VERSION_1_3;
+
+ constexpr const char* instance_layers[] = {
+ "VK_LAYER_KHRONOS_validation",
+ };
+
+ constexpr const char* instance_extensions[] = {
+ VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
+ "VK_KHR_surface",
+ "VK_KHR_win32_surface"
+ };
+
+ VkInstanceCreateInfo create_info = {};
+ create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+ create_info.pNext = nullptr;
+ create_info.flags = 0U;
+ create_info.pApplicationInfo = &app_info;
+ create_info.enabledLayerCount = sizeof(instance_layers) / sizeof(instance_layers[0]);
+ create_info.ppEnabledLayerNames = instance_layers;
+ create_info.enabledExtensionCount = sizeof(instance_extensions) / sizeof(instance_extensions[0]);
+ create_info.ppEnabledExtensionNames = instance_extensions;
+
+ VKCHECK(vkCreateInstance(&create_info, nullptr, &instance))
+
+ load_instance_functions(instance);
+}
+
+void vkdevice::create_device() {
+ pick_physical_device();
+
+ VkDeviceQueueCreateInfo queue_create_infos[QueueTypes::MAX] = {};
+ float queue_priority = 1.f;
+
+ for (auto index{ 0U }; index < QueueTypes::MAX; index++) {
+ auto& queue = queues[index];
+ auto queue_index = pick_queue(queue.usages);
+
+ queue_create_infos[index].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queue_create_infos[index].pNext = nullptr;
+ queue_create_infos[index].flags = 0U;
+ queue_create_infos[index].queueFamilyIndex = 0;
+ queue_create_infos[index].queueCount = 1;
+ queue_create_infos[index].pQueuePriorities = &queue_priority;
+
+ queue.index = queue_index;
+ }
+
+ constexpr const char* device_extensions[] = {
+ VK_KHR_SWAPCHAIN_EXTENSION_NAME,
+ };
+
+ VkPhysicalDeviceVulkan12Features physical_device_12_features = {};
+ physical_device_12_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
+ physical_device_12_features.pNext = VK_NULL_HANDLE;
+ physical_device_12_features.bufferDeviceAddress = VK_TRUE;
+ physical_device_12_features.runtimeDescriptorArray = VK_TRUE;
+ physical_device_12_features.shaderStorageImageArrayNonUniformIndexing = VK_TRUE;
+ physical_device_12_features.shaderSampledImageArrayNonUniformIndexing = VK_TRUE;
+ physical_device_12_features.descriptorBindingPartiallyBound = VK_TRUE;
+ physical_device_12_features.descriptorBindingPartiallyBound = VK_TRUE;
+ physical_device_12_features.descriptorBindingUpdateUnusedWhilePending = VK_TRUE;
+ physical_device_12_features.imagelessFramebuffer = VK_TRUE;
+
+ VkPhysicalDeviceVulkan13Features physical_device_13_features = {};
+ physical_device_13_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
+ physical_device_13_features.pNext = &physical_device_12_features;
+ physical_device_13_features.synchronization2 = VK_TRUE;
+ physical_device_13_features.dynamicRendering = VK_TRUE;
+
+ VkDeviceCreateInfo create_info = {};
+ create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ create_info.pNext = &physical_device_13_features;
+ create_info.flags = 0U;
+ create_info.queueCreateInfoCount = QueueTypes::MAX;
+ create_info.pQueueCreateInfos = queue_create_infos;
+ create_info.enabledLayerCount = 0;
+ create_info.ppEnabledLayerNames = nullptr;
+ create_info.enabledExtensionCount = sizeof(device_extensions) / sizeof(device_extensions[0]);
+ create_info.ppEnabledExtensionNames = device_extensions;
+ create_info.pEnabledFeatures = nullptr;
+
+ VKCHECK(vkCreateDevice(physical_device, &create_info, nullptr, &device))
+
+ load_device_functions(device);
+
+ for (auto& queue : queues) {
+ vkGetDeviceQueue(device, queue.index, 0, &queue.handle);
+ }
+
+ create_command_pools();
+}
+
+void vkdevice::create_memory_allocator() {
+ VmaAllocatorCreateInfo create_info = {};
+ create_info.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
+ create_info.physicalDevice = physical_device;
+ create_info.device = device;
+ create_info.instance = instance;
+ create_info.vulkanApiVersion = VK_API_VERSION_1_2;
+
+ VKCHECK(vmaCreateAllocator(&create_info, &gpu_allocator))
+}
+
+void vkdevice::create_command_pools() {
+ VkCommandPoolCreateInfo create_info = {};
+ create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ create_info.pNext = nullptr;
+ create_info.flags = 0U;
+
+ for (auto& queue : queues) {
+ create_info.queueFamilyIndex = queue.index;
+
+ VKCHECK(vkCreateCommandPool(device, &create_info, nullptr, &queue.command_pool))
+ }
+}
+
+uint32_t vkdevice::pick_queue(VkQueueFlags queue_usages) const {
+ auto queue_properties_count = 0U;
+ vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_properties_count, nullptr);
+
+ std::vector<VkQueueFamilyProperties> queue_properties{ queue_properties_count };
+ vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_properties_count, queue_properties.data());
+
+ for (auto properties_index{ 0U }; properties_index < queue_properties_count; properties_index++) {
+ if ((queue_properties[properties_index].queueFlags & queue_usages) == queue_usages) {
+ return properties_index;
+ }
+ }
+
+ assert(true);
+ return UINT_MAX;
+}
+
+void vkdevice::pick_physical_device() {
+ auto physical_devices_count = 0U;
+ vkEnumeratePhysicalDevices(instance, &physical_devices_count, nullptr);
+
+ assert(physical_devices_count > 0);
+
+ std::vector<VkPhysicalDevice> physical_devices{ physical_devices_count };
+ vkEnumeratePhysicalDevices(instance, &physical_devices_count, physical_devices.data());
+
+ for (auto& physical_dev : physical_devices) {
+ if (device_support_features(physical_dev)) {
+ physical_device = physical_dev;
+ return;
+ }
+ }
+
+ assert(true);
+}
+
+bool vkdevice::device_support_features(VkPhysicalDevice physical_dev) {
+ VkPhysicalDeviceProperties physical_device_properties = {};
+
+ vkGetPhysicalDeviceProperties(physical_dev, &physical_device_properties);
+
+ // Vulkan 1.2 physical device features support
+ {
+ VkPhysicalDeviceVulkan12Features vulkan_12_features = {};
+ vulkan_12_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
+
+ VkPhysicalDeviceFeatures2 physical_device_features = {};
+ physical_device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+ physical_device_features.pNext = &vulkan_12_features;
+
+ vkGetPhysicalDeviceFeatures2(physical_dev, &physical_device_features);
+
+ // clang-format off
+ if (vulkan_12_features.bufferDeviceAddress == VK_FALSE ||
+ vulkan_12_features.runtimeDescriptorArray == VK_FALSE ||
+ vulkan_12_features.shaderStorageImageArrayNonUniformIndexing == VK_FALSE ||
+ vulkan_12_features.shaderSampledImageArrayNonUniformIndexing == VK_FALSE ||
+ vulkan_12_features.descriptorBindingPartiallyBound == VK_FALSE ||
+ vulkan_12_features.descriptorBindingPartiallyBound == VK_FALSE ||
+ vulkan_12_features.descriptorBindingUpdateUnusedWhilePending == VK_FALSE ||
+ vulkan_12_features.imagelessFramebuffer == VK_FALSE) {
+ return false;
+ }
+ // clang-format on
+ }
+
+ // Vulkan 1.3 physical device features support
+ {
+ VkPhysicalDeviceVulkan13Features vulkan_13_features = {};
+ vulkan_13_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
+
+ VkPhysicalDeviceFeatures2 physical_device_features = {};
+ physical_device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+ physical_device_features.pNext = &vulkan_13_features;
+
+ vkGetPhysicalDeviceFeatures2(physical_dev, &physical_device_features);
+
+ if (vulkan_13_features.synchronization2 == VK_FALSE ||
+ vulkan_13_features.dynamicRendering == VK_FALSE) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void vkdevice::create_debug_layer_callback() {
+ VkDebugUtilsMessengerCreateInfoEXT create_info = {};
+ create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
+ create_info.pNext = nullptr;
+ create_info.flags = 0U;
+ create_info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+ create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
+ create_info.pfnUserCallback = debug_callback;
+ create_info.pUserData = nullptr;
+
+ VKCHECK(vkCreateDebugUtilsMessengerEXT(instance, &create_info, nullptr, &debug_messenger))
+}