#include #include #include #include "vk-context.hpp" #define VMA_IMPLEMENTATION #include "thirdparty/vk_mem_alloc.h" #ifdef _DEBUG #define VKRESULT(result) assert(result == VK_SUCCESS); #else #define VKRESULT(result) result; #endif VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT type, const VkDebugUtilsMessengerCallbackDataEXT *data, void *userData) { std::cerr << data->pMessage << std::endl; return VK_FALSE; } vkcontext::vkcontext() { load_vulkan(); create_instance(); create_device(); } vkcontext::~vkcontext() { vmaDestroyAllocator(allocator); vkDestroyDevice(device, nullptr); vkDestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); vkDestroyInstance(instance, nullptr); } void vkcontext::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_2; std::vector layers = { "VK_LAYER_KHRONOS_validation", }; std::vector extensions = { VK_EXT_DEBUG_UTILS_EXTENSION_NAME, "VK_KHR_surface", #if defined(LINUX) "VK_KHR_xcb_surface" #elif defined(WINDOWS) "VK_KHR_win32_surface" #elif defined(MACOS) "VK_EXT_metal_surface" #endif }; VkInstanceCreateInfo instance_create_info = {}; instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instance_create_info.pApplicationInfo = &app_info; instance_create_info.enabledLayerCount = layers.size(); instance_create_info.ppEnabledLayerNames = layers.data(); instance_create_info.enabledExtensionCount = extensions.size(); instance_create_info.ppEnabledExtensionNames = extensions.data(); VKRESULT(vkCreateInstance(&instance_create_info, nullptr, &instance)) load_instance_functions(instance); create_debugger(); std::cerr << "Instance ready" << std::endl; } void vkcontext::create_debugger() { VkDebugUtilsMessengerCreateInfoEXT debugUtilsMessengeCreateInfo { VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, nullptr, 0, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT, DebugCallback, nullptr, }; VKRESULT(vkCreateDebugUtilsMessengerEXT( instance, &debugUtilsMessengeCreateInfo, nullptr, &debugMessenger )) } void vkcontext::create_device() { select_physical_device(); select_queue(); VkDeviceQueueCreateInfo queue_create_info = {}; queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queue_create_info.queueFamilyIndex = queue_index; queue_create_info.queueCount = 1; float queue_priority = 1.f; queue_create_info.pQueuePriorities = &queue_priority; 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; VkPhysicalDeviceFeatures2 device_features = {}; device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; device_features.pNext = &physical_device_12_features; std::vector device_ext = { "VK_KHR_swapchain", }; VkDeviceCreateInfo device_create_info = {}; device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_create_info.pNext = &device_features; device_create_info.pQueueCreateInfos = &queue_create_info; device_create_info.queueCreateInfoCount = 1; device_create_info.ppEnabledExtensionNames = device_ext.data(); device_create_info.enabledExtensionCount = device_ext.size(); device_create_info.enabledLayerCount = 0; // Deprecated https://www.khronos.org/registry/vulkan/specs/1.2/html/chap31.html#extendingvulkan-layers-devicelayerdeprecation VKRESULT(vkCreateDevice(physical_device, &device_create_info, nullptr, &device)) load_device_functions(device); vkGetDeviceQueue(device, queue_index, 0, &queue); create_memory_allocator(); std::cerr << "Device ready" << std::endl; } void vkcontext::create_memory_allocator() { VmaAllocatorCreateInfo allocator_info = {}; allocator_info.vulkanApiVersion = VK_API_VERSION_1_2; allocator_info.physicalDevice = physical_device; allocator_info.device = device; allocator_info.instance = instance; allocator_info.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT; vmaCreateAllocator(&allocator_info, &allocator); } void vkcontext::select_physical_device() { uint32_t physical_devices_count = 0; vkEnumeratePhysicalDevices(instance, &physical_devices_count, nullptr); if (physical_devices_count < 1) { std::cerr << "No physical device found !" << std::endl; exit(1); } std::vector physical_devices { physical_devices_count }; vkEnumeratePhysicalDevices(instance, &physical_devices_count, physical_devices.data()); physical_device = physical_devices[0]; } void vkcontext::select_queue() { uint32_t queue_properties_count = 0; vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_properties_count, nullptr); std::vector queue_properties { queue_properties_count }; vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_properties_count, queue_properties.data()); for (uint32_t properties_index = 0; properties_index < queue_properties_count; properties_index++) { if (queue_properties[properties_index].queueFlags & VK_QUEUE_COMPUTE_BIT) { queue_index = properties_index; return; } } std::cerr << "No compute queue found !" << std::endl; exit(1); }