From cad3b1393b0422a335fff7777e431a0a3f06456d Mon Sep 17 00:00:00 2001 From: ladevieq Date: Tue, 29 Dec 2020 20:18:12 +0100 Subject: vulkan instance, device, etc creation refactor --- src/vk-renderer.cpp | 346 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 346 insertions(+) create mode 100644 src/vk-renderer.cpp (limited to 'src/vk-renderer.cpp') diff --git a/src/vk-renderer.cpp b/src/vk-renderer.cpp new file mode 100644 index 0000000..7156850 --- /dev/null +++ b/src/vk-renderer.cpp @@ -0,0 +1,346 @@ +#include "vk-renderer.hpp" +#include "utils.hpp" + +#define VMA_IMPLEMENTATION +#include "thirdparty/vk_mem_alloc.h" + +#include +#include +#include + +VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT _severity, + VkDebugUtilsMessageTypeFlagsEXT _type, + const VkDebugUtilsMessengerCallbackDataEXT *_data, + void *_userData) +{ + std::cerr << _data->pMessage << std::endl; + return VK_FALSE; +} + + +vkrenderer::vkrenderer() { + load_vulkan(); + + create_instance(); + create_device(); + create_pipeline(); + create_memory_allocator(); + create_command_buffer(); + create_descriptor_set(); +} + +void vkrenderer::compute(const input_data& inputs, size_t width, size_t height) { + fill_descriptor_set(inputs); + + VkCommandBufferBeginInfo cmd_buf_begin_info = {}; + cmd_buf_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + cmd_buf_begin_info.pNext = nullptr; + cmd_buf_begin_info.flags = 0; + cmd_buf_begin_info.pInheritanceInfo = nullptr; + + vkBeginCommandBuffer(command_buffer, &cmd_buf_begin_info); + + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute_pipeline_layout, 0, 1, &compute_shader_input_set, 0, nullptr); + + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, compute_pipeline); + + vkCmdDispatch(command_buffer, width, height, 1); + + vkEndCommandBuffer(command_buffer); + + VkSubmitInfo submit_info = {}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.pNext = nullptr; + submit_info.waitSemaphoreCount = 0; + submit_info.pWaitSemaphores = nullptr; + submit_info.signalSemaphoreCount = 0; + submit_info.pSignalSemaphores = nullptr; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &command_buffer; + + vkQueueSubmit(compute_queue, 1, &submit_info, VK_NULL_HANDLE); + + vkDeviceWaitIdle(device); +} + +const color* const vkrenderer::output_image() { + return mapped_data->output_image; +} + + +void vkrenderer::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 + }; + + 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(); + + vkCreateInstance(&instance_create_info, nullptr, &instance); + + load_instance_functions(instance); + + create_debugger(); + + std::cerr << "Instance ready" << std::endl; +} + +void vkrenderer::create_debugger() { + VkDebugUtilsMessengerEXT debugMessenger; + 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, + }; + + vkCreateDebugUtilsMessengerEXT( + instance, + &debugUtilsMessengeCreateInfo, + nullptr, + &debugMessenger + ); +} + +void vkrenderer::create_device() { + select_physical_device(); + select_compute_queue(); + + VkDeviceQueueCreateInfo queue_create_info = {}; + queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_create_info.queueFamilyIndex = compute_queue_index; + queue_create_info.queueCount = 1; + + float queue_priority = 1.f; + queue_create_info.pQueuePriorities = &queue_priority; + + VkPhysicalDeviceFeatures device_features = {}; + + VkDeviceCreateInfo device_create_info = {}; + device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + device_create_info.pQueueCreateInfos = &queue_create_info; + device_create_info.queueCreateInfoCount = 1; + device_create_info.pEnabledFeatures = &device_features; + device_create_info.enabledExtensionCount = 0; // None yet + device_create_info.enabledLayerCount = 0; // Deprecated https://www.khronos.org/registry/vulkan/specs/1.2/html/chap31.html#extendingvulkan-layers-devicelayerdeprecation + + vkCreateDevice(physical_device, &device_create_info, nullptr, &device); + + load_device_functions(device); + + vkGetDeviceQueue(device, compute_queue_index, 0, &compute_queue); + + std::cerr << "Device ready" << std::endl; +} + +void vkrenderer::create_pipeline() { + std::vector shader_code = get_shader_code("./shaders/compute.comp.spv"); + if (shader_code.size() == 0) { + exit(1); + } + + VkShaderModule compute_shader_module; + VkShaderModuleCreateInfo shader_create_info = {}; + shader_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shader_create_info.pNext = nullptr; + shader_create_info.flags = 0; + shader_create_info.codeSize = shader_code.size(); + shader_create_info.pCode = (uint32_t*)shader_code.data(); + + vkCreateShaderModule(device, &shader_create_info, nullptr, &compute_shader_module); + + VkPipelineShaderStageCreateInfo stage_create_info = {}; + stage_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + stage_create_info.pNext = nullptr; + stage_create_info.flags = 0; + stage_create_info.stage = VK_SHADER_STAGE_COMPUTE_BIT; + stage_create_info.module = compute_shader_module; + stage_create_info.pName = "main"; + stage_create_info.pSpecializationInfo = nullptr; + + VkDescriptorSetLayoutBinding binding = {}; + binding.binding = 0; + binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + binding.descriptorCount = 1; + binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + binding.pImmutableSamplers = 0; + + VkDescriptorSetLayoutCreateInfo descriptor_set_layout_create_info = {}; + descriptor_set_layout_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + descriptor_set_layout_create_info.pNext = nullptr; + descriptor_set_layout_create_info.flags = 0; + descriptor_set_layout_create_info.bindingCount = 1; + descriptor_set_layout_create_info.pBindings = &binding; + + vkCreateDescriptorSetLayout(device, &descriptor_set_layout_create_info, nullptr, &compute_shader_input_layout); + + VkPipelineLayoutCreateInfo layout_create_info = {}; + layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layout_create_info.pNext = nullptr; + layout_create_info.flags = 0; + layout_create_info.setLayoutCount = 1; + layout_create_info.pSetLayouts = &compute_shader_input_layout; + layout_create_info.pushConstantRangeCount = 0; + layout_create_info.pPushConstantRanges = nullptr; + + vkCreatePipelineLayout(device, &layout_create_info, nullptr, &compute_pipeline_layout); + + VkComputePipelineCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = 0; + create_info.stage = stage_create_info; + create_info.layout = compute_pipeline_layout; + + vkCreateComputePipelines( + device, + VK_NULL_HANDLE, + 1, + &create_info, + nullptr, + &compute_pipeline + ); + + std::cerr << "Compute pipeline ready" << std::endl; +} + +void vkrenderer::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; + + vmaCreateAllocator(&allocator_info, &allocator); +} + +void vkrenderer::create_command_buffer() { + VkCommandPoolCreateInfo cmd_pool_create_info = {}; + cmd_pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + cmd_pool_create_info.pNext = nullptr; + cmd_pool_create_info.flags = 0; + cmd_pool_create_info.queueFamilyIndex = compute_queue_index; + + vkCreateCommandPool(device, &cmd_pool_create_info, nullptr, &command_pool); + + VkCommandBufferAllocateInfo cmd_buf_allocate_info = {}; + cmd_buf_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + cmd_buf_allocate_info.pNext = nullptr; + cmd_buf_allocate_info.commandPool = command_pool; + cmd_buf_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + cmd_buf_allocate_info.commandBufferCount = 1; + + vkAllocateCommandBuffers(device, &cmd_buf_allocate_info, &command_buffer); +} +void vkrenderer::create_descriptor_set() { + VkDescriptorPoolSize descriptor_pool_size = {}; + descriptor_pool_size.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + descriptor_pool_size.descriptorCount = 1; + + VkDescriptorPoolCreateInfo descriptor_pool_create_info = {}; + descriptor_pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + descriptor_pool_create_info.pNext = nullptr; + descriptor_pool_create_info.flags = 0; + descriptor_pool_create_info.maxSets = 1; + descriptor_pool_create_info.poolSizeCount = 1; + descriptor_pool_create_info.pPoolSizes = &descriptor_pool_size; + + vkCreateDescriptorPool(device, &descriptor_pool_create_info, nullptr, &descriptor_pool); + + VkDescriptorSetAllocateInfo descriptor_set_allocate_info = {}; + descriptor_set_allocate_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + descriptor_set_allocate_info.pNext = nullptr; + descriptor_set_allocate_info.descriptorPool = descriptor_pool; + descriptor_set_allocate_info.descriptorSetCount = 1; + descriptor_set_allocate_info.pSetLayouts = &compute_shader_input_layout; + + vkAllocateDescriptorSets(device, &descriptor_set_allocate_info, &compute_shader_input_set); +} + +void vkrenderer::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 vkrenderer::select_compute_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) { + compute_queue_index = properties_index; + return; + } + } + + std::cerr << "No compute queue found !" << std::endl; + exit(1); +} + +void vkrenderer::fill_descriptor_set(const input_data& inputs) { + VkBufferCreateInfo buffer_info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + buffer_info.size = sizeof(path_tracer_data); + buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + + VmaAllocationCreateInfo alloc_create_info = {}; + alloc_create_info.usage = VMA_MEMORY_USAGE_GPU_TO_CPU; + + VmaAllocation allocation; + vmaCreateBuffer(allocator, &buffer_info, &alloc_create_info, &compute_shader_buffer, &allocation, nullptr); + + vmaMapMemory(allocator, allocation, (void**) &mapped_data); + std::memcpy(&mapped_data->inputs, &inputs, sizeof(inputs)); + + VkDescriptorBufferInfo descriptor_buf_info = {}; + descriptor_buf_info.buffer = compute_shader_buffer; + descriptor_buf_info.offset = 0; + descriptor_buf_info.range = VK_WHOLE_SIZE; + + VkWriteDescriptorSet write_descriptor_set = {}; + write_descriptor_set.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_descriptor_set.pNext = nullptr; + write_descriptor_set.dstSet = compute_shader_input_set; + write_descriptor_set.dstBinding = 0; + write_descriptor_set.dstArrayElement = 0; + write_descriptor_set.descriptorCount = 1; + write_descriptor_set.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + write_descriptor_set.pImageInfo = nullptr; + write_descriptor_set.pBufferInfo = &descriptor_buf_info; + write_descriptor_set.pTexelBufferView = nullptr; + + vkUpdateDescriptorSets(device, 1, &write_descriptor_set, 0, nullptr); +} -- cgit v1.3