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 --- include/rt.hpp | 2 +- include/vk-renderer.hpp | 75 ++++++++++ src/CMakeLists.txt | 1 + src/main.cpp | 370 +----------------------------------------------- src/vk-renderer.cpp | 346 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 428 insertions(+), 366 deletions(-) create mode 100644 include/vk-renderer.hpp create mode 100644 src/vk-renderer.cpp diff --git a/include/rt.hpp b/include/rt.hpp index d368ba5..570fc42 100644 --- a/include/rt.hpp +++ b/include/rt.hpp @@ -35,6 +35,6 @@ inline double clamp(double x, double min, double max) { #include "lambertian.hpp" #include "metal.hpp" #include "dielectric.hpp" -#include "utils.hpp" +#include "hittable_list.hpp" #endif // !__RT_HPP_ diff --git a/include/vk-renderer.hpp b/include/vk-renderer.hpp new file mode 100644 index 0000000..c54009f --- /dev/null +++ b/include/vk-renderer.hpp @@ -0,0 +1,75 @@ +#ifndef __VK_RENDERER_HPP_ +#define __VK_RENDERER_HPP_ + +#include "vulkan-loader.hpp" +#include "thirdparty/vk_mem_alloc.h" + +#include "vec3.hpp" + +struct input_data { + color sky_color; + color ground_color; + + float viewport_width; + float viewport_height; + float pad1; + float pad2; +}; +struct path_tracer_data { + struct input_data inputs; + color output_image[1920 * 1080]; +}; + +class vkrenderer { + public: + vkrenderer(); + + void compute(const input_data& inputs, size_t width, size_t height); + + const color* const output_image(); + + private: + void create_instance(); + + void create_debugger(); + + void create_device(); + + void create_pipeline(); + + void create_memory_allocator(); + + void create_command_buffer(); + + void create_descriptor_set(); + + void select_physical_device(); + + void select_compute_queue(); + + void fill_descriptor_set(const input_data& data); + + uint32_t compute_queue_index; + + VkInstance instance; + VkPhysicalDevice physical_device; + VkDevice device; + VkQueue compute_queue; + + VmaAllocator allocator; + VkBuffer compute_shader_buffer; + + VkCommandPool command_pool; + VkCommandBuffer command_buffer; + + VkDescriptorPool descriptor_pool; + VkDescriptorSet compute_shader_input_set; + + VkDescriptorSetLayout compute_shader_input_layout; + VkPipelineLayout compute_pipeline_layout; + VkPipeline compute_pipeline; + + struct path_tracer_data* mapped_data; +}; + +#endif // !__VK_RENDERER_HPP_ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 801d4f1..c185ebe 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,6 +15,7 @@ add_executable( dielectric.cpp vulkan-loader.cpp utils.cpp + vk-renderer.cpp ) if(UNIX) diff --git a/src/main.cpp b/src/main.cpp index 53d116c..7dcf801 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,13 +3,9 @@ #include #include -#include "vulkan-loader.hpp" - -#define VMA_IMPLEMENTATION -#include "thirdparty/vk_mem_alloc.h" +#include "vk-renderer.hpp" #include "rt.hpp" -#include "hittable_list.hpp" color ground_color { 1.0, 1.0, 1.0 }; color sky_color { 0.5, 0.7, 1.0 }; @@ -81,362 +77,8 @@ color ray_color(ray& r, const hittable& world, uint32_t depth) { return lerp(ground_color, sky_color, t); } -VkInstance instance = nullptr; -VkPhysicalDevice physical_device = nullptr; -int32_t compute_queue_index = -1; -VkDevice device = nullptr; -VkQueue compute_queue = nullptr; - -VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT _severity, - VkDebugUtilsMessageTypeFlagsEXT _type, - const VkDebugUtilsMessengerCallbackDataEXT *_data, - void *_userData) -{ - std::cerr << _data->pMessage << std::endl; - return VK_FALSE; -} - -void create_debugger(VkInstance instance) { - 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 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; - - - const char* layers[1] = { - "VK_LAYER_KHRONOS_validation", - }; - const char* ext[1] = { - 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 = 1; - instance_create_info.ppEnabledLayerNames = layers; - instance_create_info.enabledExtensionCount = 1; - instance_create_info.ppEnabledExtensionNames = ext; - - vkCreateInstance(&instance_create_info, nullptr, &instance); - - load_instance_functions(instance); - create_debugger(instance); - - std::cerr << "Instance ready" << std::endl; -} - -void 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]; -} - -int32_t get_compute_queue_index() { - 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) { - return properties_index; - } - } - - return -1; -} - -void create_device() { - select_physical_device(); - - compute_queue_index = get_compute_queue_index(); - 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; // 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; -} - -VkPipeline compute_pipeline = nullptr; -VkDescriptorSetLayout compute_shader_input_layout = nullptr; -VkPipelineLayout compute_pipeline_layout = nullptr; -void 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; -} - -VmaAllocator allocator = nullptr; -void 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); -} - -VkCommandPool command_pool = nullptr; -VkCommandBuffer cmd_buf = nullptr; -void 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, &cmd_buf); -} - -VkDescriptorPool descriptor_pool = nullptr; -VkDescriptorSet compute_shader_input_set = nullptr; -void 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); -} - -struct input_data { - color sky_color; - color ground_color; - float viewport_width; - float viewport_height; - float pad1; - float pad2; -}; -struct path_tracer_data { - struct input_data inputs; - color output_image[1920 * 1080]; -}; - -struct path_tracer_data* mapped_data; -VkBuffer compute_shader_input_buffer; -void 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_input_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_input_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); -} - -void init_vk() { - create_instance(); - create_device(); - create_pipeline(); - create_command_buffer(); - create_descriptor_set(); - create_memory_allocator(); -} - -void compute(size_t width, size_t height) { - 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(cmd_buf, &cmd_buf_begin_info); - - vkCmdBindDescriptorSets(cmd_buf, VK_PIPELINE_BIND_POINT_COMPUTE, compute_pipeline_layout, 0, 1, &compute_shader_input_set, 0, nullptr); - - vkCmdBindPipeline(cmd_buf, VK_PIPELINE_BIND_POINT_COMPUTE, compute_pipeline); - - vkCmdDispatch(cmd_buf, width, height, 1); - - vkEndCommandBuffer(cmd_buf); - - 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 = &cmd_buf; - - vkQueueSubmit(compute_queue, 1, &submit_info, VK_NULL_HANDLE); - - vkDeviceWaitIdle(device); -} - int main() { - load_vulkan(); - init_vk(); + vkrenderer renderer {}; // Image dimensions const double aspect_ratio = 16.0 / 9.0; @@ -453,26 +95,24 @@ int main() { struct input_data inputs = { .sky_color = sky_color, .ground_color = ground_color, - .viewport_width = camera.viewport_width, - .viewport_height = camera.viewport_height }; // World hittable objects hittable_list world = random_scene(); - fill_descriptor_set(inputs); // PPM format header std::cout << "P3\n" << width << '\n' << height << "\n255" << std::endl; std::cerr << "Generating image" << std::endl; - compute(width, height); + renderer.compute(inputs, width, height); //------------------------- // GPU path tracer //------------------------- + auto output_image = renderer.output_image(); for (size_t index = 0; index < height * width; index++) { - write_color(std::cout, mapped_data->output_image[index], samples_per_pixel); + write_color(std::cout, output_image[index], samples_per_pixel); } //--------------------------- 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