|
|
@@ -4,10 +4,17 @@
|
|
|
#include <SDL_vulkan.h>
|
|
|
|
|
|
#include <vk_initializers.h>
|
|
|
-#include <vk_types.h>
|
|
|
+#include <vk_pipelines.h>
|
|
|
#include <vk_images.h>
|
|
|
|
|
|
-#include "VkBootstrap.h"
|
|
|
+#define VMA_IMPLEMENTATION
|
|
|
+#include <vk_mem_alloc.h>
|
|
|
+#include <VkBootstrap.h>
|
|
|
+
|
|
|
+// IMGUI
|
|
|
+#include <imgui.h>
|
|
|
+#include <imgui_impl_sdl2.h>
|
|
|
+#include <imgui_impl_vulkan.h>
|
|
|
|
|
|
#include <chrono>
|
|
|
#include <thread>
|
|
|
@@ -40,6 +47,10 @@ void VulkanEngine::init()
|
|
|
_windowExtent.height,
|
|
|
window_flags);
|
|
|
|
|
|
+ _mainDeletionQueue.push([&](){
|
|
|
+ SDL_DestroyWindow(_window);
|
|
|
+ });
|
|
|
+
|
|
|
init_vulkan();
|
|
|
|
|
|
init_swapchain();
|
|
|
@@ -48,6 +59,12 @@ void VulkanEngine::init()
|
|
|
|
|
|
init_sync_structures();
|
|
|
|
|
|
+ init_descriptors();
|
|
|
+
|
|
|
+ init_pipelines();
|
|
|
+
|
|
|
+ init_imgui();
|
|
|
+
|
|
|
// everything went fine
|
|
|
_isInitialized = true;
|
|
|
}
|
|
|
@@ -62,22 +79,10 @@ void VulkanEngine::cleanup()
|
|
|
// Cleanup frame data
|
|
|
for (auto & frame : _frames)
|
|
|
{
|
|
|
- vkDestroyCommandPool(_device, frame._commandPool, nullptr);
|
|
|
-
|
|
|
- // Sync structures
|
|
|
- vkDestroyFence(_device, frame._renderFence, nullptr);
|
|
|
- vkDestroySemaphore(_device, frame._renderSemaphore, nullptr);
|
|
|
- vkDestroySemaphore(_device, frame._swapchainSemaphore, nullptr);
|
|
|
+ frame._deletionQueue.flush();
|
|
|
}
|
|
|
|
|
|
- destroy_swapchain();
|
|
|
-
|
|
|
- vkDestroySurfaceKHR(_instance, _surface, nullptr);
|
|
|
- vkDestroyDevice(_device, nullptr);
|
|
|
-
|
|
|
- vkb::destroy_debug_utils_messenger(_instance, _debugMessenger);
|
|
|
- vkDestroyInstance(_instance, nullptr);
|
|
|
- SDL_DestroyWindow(_window);
|
|
|
+ _mainDeletionQueue.flush();
|
|
|
}
|
|
|
|
|
|
loadedEngine = nullptr;
|
|
|
@@ -89,6 +94,8 @@ void VulkanEngine::draw()
|
|
|
VK_CHECK(vkWaitForFences(_device, 1, &get_current_frame()._renderFence, true, 1000000000));
|
|
|
VK_CHECK(vkResetFences(_device, 1, &get_current_frame()._renderFence));
|
|
|
|
|
|
+ get_current_frame()._deletionQueue.flush();
|
|
|
+
|
|
|
// Request swapchain image
|
|
|
uint32_t swapchainImageIndex;
|
|
|
VK_CHECK(vkAcquireNextImageKHR(_device, _swapchain, 1000000000, get_current_frame()._swapchainSemaphore, nullptr,
|
|
|
@@ -103,37 +110,44 @@ void VulkanEngine::draw()
|
|
|
// Command buffer will be used exactly once
|
|
|
VkCommandBufferBeginInfo cmdBeginInfo = vkinit::command_buffer_begin_info(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
|
|
|
|
|
- // Start recording
|
|
|
+ _drawExtent.width = _drawImage.imageExtent.width;
|
|
|
+ _drawExtent.height = _drawImage.imageExtent.height;
|
|
|
+
|
|
|
+ // Begin recording
|
|
|
VK_CHECK(vkBeginCommandBuffer(cmd, &cmdBeginInfo));
|
|
|
|
|
|
- // Transition swapchain image to writable
|
|
|
- vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_UNDEFINED,
|
|
|
- VK_IMAGE_LAYOUT_GENERAL);
|
|
|
+ // Transition draw image to general layout for writing into it
|
|
|
+ vkutil::transition_image(cmd, _drawImage.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
|
|
|
|
|
|
- // Flash clear color every 120 frames
|
|
|
- VkClearColorValue clearValue;
|
|
|
- float flash = abs(sin(_frameNumber / 120.f));
|
|
|
- clearValue = { { 0.0f, 0.0f, flash, 1.0f } };
|
|
|
+ draw_clear_color(cmd);
|
|
|
|
|
|
- VkImageSubresourceRange clearRange = vkinit::image_subresource_range(VK_IMAGE_ASPECT_COLOR_BIT);
|
|
|
+ // Transition draw image and swapchain image to correct layout for transferring
|
|
|
+ vkutil::transition_image(cmd, _drawImage.image, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
|
|
+ vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
|
|
|
|
|
- // Clear image
|
|
|
- vkCmdClearColorImage(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_GENERAL, &clearValue, 1, &clearRange);
|
|
|
+ // Copy draw image to swapchain image
|
|
|
+ vkutil::copy_image_to_image(cmd, _drawImage.image, _swapchainImages[swapchainImageIndex], _drawExtent, _swapchainExtent);
|
|
|
|
|
|
- // Transition swapchain image to presentable
|
|
|
- vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex],VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
|
|
+ // Set swapchain image to Attachment Optimal, so we can directly draw to it
|
|
|
+ vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
|
|
|
|
|
- // Finalize command buffer for execution
|
|
|
+ // Draw IMGUI into swapchain image
|
|
|
+ draw_imgui(cmd, _swapchainImageViews[swapchainImageIndex]);
|
|
|
+
|
|
|
+ // Transition swapchain image to presentable layout
|
|
|
+ vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
|
|
+
|
|
|
+ // End recording to command buffer
|
|
|
VK_CHECK(vkEndCommandBuffer(cmd));
|
|
|
|
|
|
// Wait for swapchain to be ready (_presentSemaphore)
|
|
|
- // Signal when renderign has finished (_renderSemaphore)
|
|
|
- VkCommandBufferSubmitInfo cmdinfo = vkinit::command_buffer_submit_info(cmd);
|
|
|
+ // Signal when rendering has finished (_renderSemaphore)
|
|
|
+ VkCommandBufferSubmitInfo cmdInfo = vkinit::command_buffer_submit_info(cmd);
|
|
|
|
|
|
VkSemaphoreSubmitInfo waitInfo = vkinit::semaphore_submit_info(VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR,get_current_frame()._swapchainSemaphore);
|
|
|
VkSemaphoreSubmitInfo signalInfo = vkinit::semaphore_submit_info(VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT, get_current_frame()._renderSemaphore);
|
|
|
|
|
|
- VkSubmitInfo2 submit = vkinit::submit_info(&cmdinfo,&signalInfo,&waitInfo);
|
|
|
+ VkSubmitInfo2 submit = vkinit::submit_info(&cmdInfo, &signalInfo, &waitInfo);
|
|
|
|
|
|
// Submit to queue and execute
|
|
|
// Block until queue finishes execution (_renderFence)
|
|
|
@@ -180,6 +194,8 @@ void VulkanEngine::run()
|
|
|
_stopRendering = false;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ ImGui_ImplSDL2_ProcessEvent(&e);
|
|
|
}
|
|
|
|
|
|
// do not draw if we are minimized
|
|
|
@@ -189,6 +205,17 @@ void VulkanEngine::run()
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
+ // New IMGUI frame
|
|
|
+ ImGui_ImplVulkan_NewFrame();
|
|
|
+ ImGui_ImplSDL2_NewFrame(_window);
|
|
|
+ ImGui::NewFrame();
|
|
|
+
|
|
|
+ // Debug
|
|
|
+ ImGui::ShowDemoWindow();
|
|
|
+
|
|
|
+ // Render IMGUI
|
|
|
+ ImGui::Render();
|
|
|
+
|
|
|
draw();
|
|
|
}
|
|
|
}
|
|
|
@@ -243,28 +270,101 @@ void VulkanEngine::init_vulkan()
|
|
|
|
|
|
_graphicsQueue = vkbDevice.get_queue(vkb::QueueType::graphics).value();
|
|
|
_graphicsQueueFamily = vkbDevice.get_queue_index(vkb::QueueType::graphics).value();
|
|
|
+
|
|
|
+ // Initialize VMA
|
|
|
+ VmaAllocatorCreateInfo allocInfo{};
|
|
|
+ allocInfo.physicalDevice = _physicalGPU;
|
|
|
+ allocInfo.device = _device;
|
|
|
+ allocInfo.instance = _instance;
|
|
|
+ allocInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
|
|
|
+ vmaCreateAllocator(&allocInfo, &_allocator);
|
|
|
+
|
|
|
+ _mainDeletionQueue.push([&](){
|
|
|
+ vmaDestroyAllocator(_allocator);
|
|
|
+ vkDestroySurfaceKHR(_instance, _surface, nullptr);
|
|
|
+
|
|
|
+ vkDestroyDevice(_device, nullptr);
|
|
|
+ vkb::destroy_debug_utils_messenger(_instance, _debugMessenger);
|
|
|
+ vkDestroyInstance(_instance, nullptr);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
void VulkanEngine::init_swapchain()
|
|
|
{
|
|
|
create_swapchain(_windowExtent.width, _windowExtent.height);
|
|
|
+
|
|
|
+ // Create draw image
|
|
|
+ _drawImage.imageFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
|
|
|
+ _drawImage.imageExtent = {
|
|
|
+ _windowExtent.width,
|
|
|
+ _windowExtent.height,
|
|
|
+ 1
|
|
|
+ };;
|
|
|
+
|
|
|
+ VkImageUsageFlags drawImageUsages{};
|
|
|
+ drawImageUsages |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
|
|
+ drawImageUsages |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
|
|
+ drawImageUsages |= VK_IMAGE_USAGE_STORAGE_BIT;
|
|
|
+ drawImageUsages |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
|
|
+
|
|
|
+ VkImageCreateInfo imgCI = vkinit::image_create_info(_drawImage.imageFormat, drawImageUsages,
|
|
|
+ _drawImage.imageExtent);
|
|
|
+
|
|
|
+ // Allocate the draw image from device (GPU) local memory
|
|
|
+ VmaAllocationCreateInfo imgAllocCI{};
|
|
|
+ imgAllocCI.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
|
|
+ imgAllocCI.requiredFlags = VkMemoryPropertyFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
|
|
+
|
|
|
+ // Allocate image
|
|
|
+ vmaCreateImage(_allocator, &imgCI, &imgAllocCI, &_drawImage.image, &_drawImage.allocation, nullptr);
|
|
|
+
|
|
|
+ // Build image view for draw image
|
|
|
+ VkImageViewCreateInfo imgViewCI = vkinit::imageview_create_info(_drawImage.imageFormat, _drawImage.image,
|
|
|
+ VK_IMAGE_ASPECT_COLOR_BIT);
|
|
|
+
|
|
|
+ VK_CHECK(vkCreateImageView(_device, &imgViewCI, nullptr, &_drawImage.imageView));
|
|
|
+
|
|
|
+ _mainDeletionQueue.push([=, this](){
|
|
|
+ vkDestroyImageView(_device, _drawImage.imageView, nullptr);
|
|
|
+ vmaDestroyImage(_allocator, _drawImage.image, _drawImage.allocation);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
void VulkanEngine::init_commands()
|
|
|
{
|
|
|
// Create command pool for commands submitted to the graphics queue
|
|
|
// and allow resetting individual command buffers;
|
|
|
- VkCommandPoolCreateInfo commandPoolInfo = vkinit::command_pool_create_info(_graphicsQueueFamily,
|
|
|
- VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
|
|
|
+ VkCommandPoolCreateInfo commandPoolInfo
|
|
|
+ {
|
|
|
+ vkinit::command_pool_create_info(_graphicsQueueFamily,
|
|
|
+ VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)
|
|
|
+ };
|
|
|
|
|
|
- for (auto & frame : _frames)
|
|
|
+ // Initialize immediate buffer
|
|
|
+ VK_CHECK(vkCreateCommandPool(_device, &commandPoolInfo, nullptr, &_immediateBuffer._commandPool));
|
|
|
+
|
|
|
+ VkCommandBufferAllocateInfo immCmdAllocInfo
|
|
|
+ {
|
|
|
+ vkinit::command_buffer_allocate_info(_immediateBuffer._commandPool,1)
|
|
|
+ };
|
|
|
+ VK_CHECK(vkAllocateCommandBuffers(_device, &immCmdAllocInfo, &_immediateBuffer._commandBuffer));
|
|
|
+
|
|
|
+ _mainDeletionQueue.push([=, this]() {
|
|
|
+ vkDestroyCommandPool(_device, _immediateBuffer._commandPool, nullptr);
|
|
|
+ });
|
|
|
+
|
|
|
+ for (auto & frame : _frames)
|
|
|
{
|
|
|
VK_CHECK(vkCreateCommandPool(_device, &commandPoolInfo, nullptr, &frame._commandPool));
|
|
|
|
|
|
// Allocate default command buffer used for rendering
|
|
|
- VkCommandBufferAllocateInfo cmdAllocInfo = vkinit::command_buffer_allocate_info(frame._commandPool, 1);
|
|
|
+ VkCommandBufferAllocateInfo cmdAllocInfo {vkinit::command_buffer_allocate_info(frame._commandPool, 1)};
|
|
|
|
|
|
VK_CHECK(vkAllocateCommandBuffers(_device, &cmdAllocInfo, &frame._mainCommandBuffer));
|
|
|
+
|
|
|
+ _mainDeletionQueue.push([=, this](){
|
|
|
+ vkDestroyCommandPool(_device, frame._commandPool, nullptr);
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -276,12 +376,25 @@ void VulkanEngine::init_sync_structures()
|
|
|
VkFenceCreateInfo fenceCreateInfo = vkinit::fence_create_info(VK_FENCE_CREATE_SIGNALED_BIT);
|
|
|
VkSemaphoreCreateInfo semaphoreCreateInfo = vkinit::semaphore_create_info();
|
|
|
|
|
|
+ VK_CHECK(vkCreateFence(_device, &fenceCreateInfo, nullptr, &_immediateBuffer._fence));
|
|
|
+
|
|
|
+ _mainDeletionQueue.push([=, this](){
|
|
|
+ vkDestroyFence(_device, _immediateBuffer._fence, nullptr);
|
|
|
+ });
|
|
|
+
|
|
|
for (auto & frame : _frames)
|
|
|
{
|
|
|
VK_CHECK(vkCreateFence(_device, &fenceCreateInfo, nullptr, &frame._renderFence));
|
|
|
|
|
|
VK_CHECK(vkCreateSemaphore(_device, &semaphoreCreateInfo, nullptr, &frame._swapchainSemaphore));
|
|
|
VK_CHECK(vkCreateSemaphore(_device, &semaphoreCreateInfo, nullptr, &frame._renderSemaphore));
|
|
|
+
|
|
|
+ // Deletion queue
|
|
|
+ _mainDeletionQueue.push([=, this](){
|
|
|
+ vkDestroyFence(_device, frame._renderFence, nullptr);
|
|
|
+ vkDestroySemaphore(_device, frame._renderSemaphore, nullptr);
|
|
|
+ vkDestroySemaphore(_device, frame._swapchainSemaphore, nullptr);
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -306,14 +419,213 @@ void VulkanEngine::create_swapchain(uint32_t width, uint32_t height)
|
|
|
_swapchain = vkbSwapchain.swapchain;
|
|
|
_swapchainImages = vkbSwapchain.get_images().value();
|
|
|
_swapchainImageViews = vkbSwapchain.get_image_views().value();
|
|
|
+
|
|
|
+ _mainDeletionQueue.push([=, this](){
|
|
|
+ vkDestroySwapchainKHR(_device, _swapchain, nullptr);
|
|
|
+ for (int i = 0; i < _swapchainImageViews.size(); ++i)
|
|
|
+ {
|
|
|
+ vkDestroyImageView(_device, _swapchainImageViews[i], nullptr);
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+void VulkanEngine::draw_clear_color(VkCommandBuffer cmd)
|
|
|
+{
|
|
|
+ // bind the gradient drawing compute pipeline
|
|
|
+ vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, _computePipeline);
|
|
|
+
|
|
|
+ // bind the descriptor set containing the draw image for the compute pipeline
|
|
|
+ vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, _computePipelineLayout, 0, 1, &_drawImageDescriptors, 0, nullptr);
|
|
|
+
|
|
|
+ // execute the compute pipeline dispatch. We are using 16x16 workgroup size so we need to divide by it
|
|
|
+ vkCmdDispatch(cmd, std::ceil(_drawExtent.width / 16.0), std::ceil(_drawExtent.height / 16.0), 1);
|
|
|
+}
|
|
|
+
|
|
|
+void VulkanEngine::init_descriptors()
|
|
|
+{
|
|
|
+ std::vector<DescriptorAllocator::PoolSizeRatio> sizes
|
|
|
+ {
|
|
|
+ {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1}
|
|
|
+ };
|
|
|
+
|
|
|
+ _globalDescriptorAllocator.init_pool(_device, 10, sizes);
|
|
|
+
|
|
|
+ {
|
|
|
+ DescriptorLayoutBuilder layoutBuilder;
|
|
|
+ layoutBuilder.add_binding(0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
|
|
|
+ _drawImageDescriptorLayout = layoutBuilder.build(_device, VK_SHADER_STAGE_COMPUTE_BIT);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Allocate descriptor for draw image
|
|
|
+ _drawImageDescriptors = _globalDescriptorAllocator.allocate(_device, _drawImageDescriptorLayout);
|
|
|
+
|
|
|
+ // The DescImageInfo holds a "pointer" to the resource that will get bound to the descriptor
|
|
|
+ VkDescriptorImageInfo imgInfo
|
|
|
+ {
|
|
|
+ .imageView = _drawImage.imageView,
|
|
|
+ .imageLayout = VK_IMAGE_LAYOUT_GENERAL
|
|
|
+ };
|
|
|
+
|
|
|
+ // A write is used to "write" the resource into the descriptor set
|
|
|
+ VkWriteDescriptorSet drawImageWrite
|
|
|
+ {
|
|
|
+ .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
|
+ .pNext = nullptr,
|
|
|
+
|
|
|
+ .dstSet = _drawImageDescriptors,
|
|
|
+ .dstBinding = 0,
|
|
|
+ .descriptorCount = 1,
|
|
|
+ .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
|
|
+ .pImageInfo = &imgInfo
|
|
|
+ };
|
|
|
+
|
|
|
+ vkUpdateDescriptorSets(_device, 1, &drawImageWrite, 0, nullptr);
|
|
|
+
|
|
|
+ _mainDeletionQueue.push([&](){
|
|
|
+ _globalDescriptorAllocator.destroy_pool(_device);
|
|
|
+ vkDestroyDescriptorSetLayout(_device, _drawImageDescriptorLayout, nullptr);
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
-void VulkanEngine::destroy_swapchain()
|
|
|
+void VulkanEngine::init_pipelines()
|
|
|
{
|
|
|
- vkDestroySwapchainKHR(_device, _swapchain, nullptr);
|
|
|
+ init_background_pipelines();
|
|
|
+}
|
|
|
|
|
|
- for (int i = 0; i < _swapchainImageViews.size(); ++i)
|
|
|
+void VulkanEngine::init_background_pipelines()
|
|
|
+{
|
|
|
+ VkPipelineLayoutCreateInfo computeLayout{};
|
|
|
+ computeLayout.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
|
|
+ computeLayout.pNext = nullptr;
|
|
|
+ computeLayout.pSetLayouts = &_drawImageDescriptorLayout;
|
|
|
+ computeLayout.setLayoutCount = 1;
|
|
|
+
|
|
|
+ VK_CHECK(vkCreatePipelineLayout(_device, &computeLayout, nullptr, &_computePipelineLayout));
|
|
|
+
|
|
|
+ VkShaderModule computeDrawShader;
|
|
|
+ if (!vkutil::load_shader_module("../shaders/gradient.comp.spv", _device, &computeDrawShader))
|
|
|
{
|
|
|
- vkDestroyImageView(_device, _swapchainImageViews[i], nullptr);
|
|
|
+ fmt::print("Error when building the compute shader \n");
|
|
|
}
|
|
|
+
|
|
|
+ VkPipelineShaderStageCreateInfo stageinfo{};
|
|
|
+ stageinfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
|
|
+ stageinfo.pNext = nullptr;
|
|
|
+ stageinfo.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
|
|
+ stageinfo.module = computeDrawShader;
|
|
|
+ stageinfo.pName = "main";
|
|
|
+
|
|
|
+ VkComputePipelineCreateInfo computePipelineCreateInfo{};
|
|
|
+ computePipelineCreateInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
|
|
+ computePipelineCreateInfo.pNext = nullptr;
|
|
|
+ computePipelineCreateInfo.layout = _computePipelineLayout;
|
|
|
+ computePipelineCreateInfo.stage = stageinfo;
|
|
|
+
|
|
|
+ VK_CHECK(vkCreateComputePipelines(_device,VK_NULL_HANDLE,1,&computePipelineCreateInfo, nullptr, &_computePipeline));
|
|
|
+
|
|
|
+ vkDestroyShaderModule(_device, computeDrawShader, nullptr);
|
|
|
+
|
|
|
+ _mainDeletionQueue.push([&]() {
|
|
|
+ vkDestroyPipelineLayout(_device, _computePipelineLayout, nullptr);
|
|
|
+ vkDestroyPipeline(_device, _computePipeline, nullptr);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+void VulkanEngine::draw_imgui(VkCommandBuffer cmd, VkImageView targetImageView)
|
|
|
+{
|
|
|
+ VkRenderingAttachmentInfo colorAttachment = vkinit::attachment_info(targetImageView, nullptr, VK_IMAGE_LAYOUT_GENERAL);
|
|
|
+ VkRenderingInfo renderInfo = vkinit::rendering_info(_swapchainExtent, &colorAttachment, nullptr);
|
|
|
+
|
|
|
+ vkCmdBeginRendering(cmd, &renderInfo);
|
|
|
+
|
|
|
+ ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd);
|
|
|
+
|
|
|
+ vkCmdEndRendering(cmd);
|
|
|
+}
|
|
|
+
|
|
|
+void VulkanEngine::immediate_submit(std::function<void(VkCommandBuffer)> &&function)
|
|
|
+{
|
|
|
+ VK_CHECK(vkResetFences(_device, 1, &_immediateBuffer._fence));
|
|
|
+ VK_CHECK(vkResetCommandBuffer(_immediateBuffer._commandBuffer, 0));
|
|
|
+
|
|
|
+ VkCommandBuffer cmd = _immediateBuffer._commandBuffer;
|
|
|
+
|
|
|
+ VkCommandBufferBeginInfo cmdBeginInfo = vkinit::command_buffer_begin_info(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
|
|
+
|
|
|
+ VK_CHECK(vkBeginCommandBuffer(cmd, &cmdBeginInfo));
|
|
|
+
|
|
|
+ function(cmd);
|
|
|
+
|
|
|
+ VK_CHECK(vkEndCommandBuffer(cmd));
|
|
|
+
|
|
|
+ VkCommandBufferSubmitInfo cmdinfo = vkinit::command_buffer_submit_info(cmd);
|
|
|
+ VkSubmitInfo2 submit = vkinit::submit_info(&cmdinfo, nullptr, nullptr);
|
|
|
+
|
|
|
+
|
|
|
+ // Submit and execute command buffer
|
|
|
+ VK_CHECK(vkQueueSubmit2(_graphicsQueue, 1, &submit, _immediateBuffer._fence));
|
|
|
+
|
|
|
+ // _fence will block until graphic commands execution have finished execution
|
|
|
+ VK_CHECK(vkWaitForFences(_device, 1, &_immediateBuffer._fence, true, 9999999999));
|
|
|
}
|
|
|
+
|
|
|
+void VulkanEngine::init_imgui()
|
|
|
+{
|
|
|
+ // Create descriptor pool used by IMGUI
|
|
|
+ // Pool size is oversize but as provided by imgui demo
|
|
|
+ VkDescriptorPoolSize pool_sizes[] = { { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
|
|
|
+ { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
|
|
|
+ { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
|
|
|
+ { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
|
|
|
+ { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
|
|
|
+ { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
|
|
|
+ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
|
|
|
+ { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
|
|
|
+ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
|
|
|
+ { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
|
|
|
+ { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 } };
|
|
|
+
|
|
|
+ VkDescriptorPoolCreateInfo pool_info = {};
|
|
|
+ pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
|
|
+ pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
|
|
+ pool_info.maxSets = 1000;
|
|
|
+ pool_info.poolSizeCount = (uint32_t)std::size(pool_sizes);
|
|
|
+ pool_info.pPoolSizes = pool_sizes;
|
|
|
+
|
|
|
+ VkDescriptorPool imguiPool;
|
|
|
+ VK_CHECK(vkCreateDescriptorPool(_device, &pool_info, nullptr, &imguiPool));
|
|
|
+
|
|
|
+
|
|
|
+ // Initialize IMGUI structures
|
|
|
+ ImGui::CreateContext();
|
|
|
+
|
|
|
+ // Initialize IMGUI for SDL
|
|
|
+ ImGui_ImplSDL2_InitForVulkan(_window);
|
|
|
+
|
|
|
+ // Initialize IMGUI for Vulkan
|
|
|
+ ImGui_ImplVulkan_InitInfo init_info = {};
|
|
|
+ init_info.Instance = _instance;
|
|
|
+ init_info.PhysicalDevice = _physicalGPU;
|
|
|
+ init_info.Device = _device;
|
|
|
+ init_info.Queue = _graphicsQueue;
|
|
|
+ init_info.DescriptorPool = imguiPool;
|
|
|
+ init_info.MinImageCount = 3;
|
|
|
+ init_info.ImageCount = 3;
|
|
|
+ init_info.UseDynamicRendering = true;
|
|
|
+ init_info.ColorAttachmentFormat = _swapchainImageFormat;
|
|
|
+
|
|
|
+ init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
|
|
|
+
|
|
|
+ ImGui_ImplVulkan_Init(&init_info, VK_NULL_HANDLE);
|
|
|
+
|
|
|
+ // Upload font textures to GPU
|
|
|
+ immediate_submit([&](VkCommandBuffer cmd) { ImGui_ImplVulkan_CreateFontsTexture(cmd); });
|
|
|
+
|
|
|
+ // Clear font textures from CPU
|
|
|
+ ImGui_ImplVulkan_DestroyFontUploadObjects();
|
|
|
+
|
|
|
+ _mainDeletionQueue.push([=, this]() {
|
|
|
+ vkDestroyDescriptorPool(_device, imguiPool, nullptr);
|
|
|
+ ImGui_ImplVulkan_Shutdown();
|
|
|
+ });
|
|
|
+}
|