| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631 |
- #include "vk_engine.h"
- #include <SDL.h>
- #include <SDL_vulkan.h>
- #include <vk_initializers.h>
- #include <vk_pipelines.h>
- #include <vk_images.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>
- VulkanEngine* loadedEngine = nullptr;
- VulkanEngine& VulkanEngine::Get() { return *loadedEngine; }
- #ifdef NDEBUG
- constexpr bool bUseValidationLayers = false;
- #else
- constexpr bool bUseValidationLayers = true;
- #endif
- void VulkanEngine::init()
- {
- // only one engine initialization is allowed with the application.
- assert(loadedEngine == nullptr);
- loadedEngine = this;
- // We initialize SDL and create a window with it.
- SDL_Init(SDL_INIT_VIDEO);
- SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN);
- _window = SDL_CreateWindow(
- "Coral3D",
- SDL_WINDOWPOS_UNDEFINED,
- SDL_WINDOWPOS_UNDEFINED,
- _windowExtent.width,
- _windowExtent.height,
- window_flags);
- _mainDeletionQueue.push([&](){
- SDL_DestroyWindow(_window);
- });
- init_vulkan();
- init_swapchain();
- init_commands();
- init_sync_structures();
- init_descriptors();
- init_pipelines();
- init_imgui();
- // everything went fine
- _isInitialized = true;
- }
- void VulkanEngine::cleanup()
- {
- if (_isInitialized)
- {
- // Wait for GPU
- vkDeviceWaitIdle(_device);
- // Cleanup frame data
- for (auto & frame : _frames)
- {
- frame._deletionQueue.flush();
- }
- _mainDeletionQueue.flush();
- }
- loadedEngine = nullptr;
- }
- void VulkanEngine::draw()
- {
- // Wait for GPU to finish rendering last frame, timeout: 1 second
- 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,
- &swapchainImageIndex));
- // Get current frames command buffer
- VkCommandBuffer cmd = get_current_frame()._mainCommandBuffer;
- // Commands finished executing, reset command buffer
- VK_CHECK(vkResetCommandBuffer(cmd, 0));
- // Command buffer will be used exactly once
- VkCommandBufferBeginInfo cmdBeginInfo = vkinit::command_buffer_begin_info(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
- _drawExtent.width = _drawImage.imageExtent.width;
- _drawExtent.height = _drawImage.imageExtent.height;
- // Begin recording
- VK_CHECK(vkBeginCommandBuffer(cmd, &cmdBeginInfo));
- // Transition draw image to general layout for writing into it
- vkutil::transition_image(cmd, _drawImage.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
- draw_clear_color(cmd);
- // 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);
- // Copy draw image to swapchain image
- vkutil::copy_image_to_image(cmd, _drawImage.image, _swapchainImages[swapchainImageIndex], _drawExtent, _swapchainExtent);
- // 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);
- // 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 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);
- // Submit to queue and execute
- // Block until queue finishes execution (_renderFence)
- VK_CHECK(vkQueueSubmit2(_graphicsQueue, 1, &submit, get_current_frame()._renderFence));
- // Wait for drawing commands to have finished (_renderSemaphore)
- // Then display the image
- VkPresentInfoKHR presentInfo = {};
- presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
- presentInfo.pNext = nullptr;
- presentInfo.pSwapchains = &_swapchain;
- presentInfo.swapchainCount = 1;
- presentInfo.pWaitSemaphores = &get_current_frame()._renderSemaphore;
- presentInfo.waitSemaphoreCount = 1;
- presentInfo.pImageIndices = &swapchainImageIndex;
- VK_CHECK(vkQueuePresentKHR(_graphicsQueue, &presentInfo));
- _frameNumber++;
- }
- void VulkanEngine::run()
- {
- SDL_Event e;
- bool bQuit = false;
- while (!bQuit)
- {
- while (SDL_PollEvent(&e) != 0)
- {
- if (e.type == SDL_QUIT)
- bQuit = true;
- if (e.type == SDL_WINDOWEVENT)
- {
- if (e.window.event == SDL_WINDOWEVENT_MINIMIZED)
- {
- _stopRendering = true;
- }
- if (e.window.event == SDL_WINDOWEVENT_RESTORED)
- {
- _stopRendering = false;
- }
- }
- ImGui_ImplSDL2_ProcessEvent(&e);
- }
- // do not draw if we are minimized
- if (_stopRendering)
- {
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
- continue;
- }
- // New IMGUI frame
- ImGui_ImplVulkan_NewFrame();
- ImGui_ImplSDL2_NewFrame(_window);
- ImGui::NewFrame();
- // Debug
- ImGui::ShowDemoWindow();
- // Render IMGUI
- ImGui::Render();
- draw();
- }
- }
- void VulkanEngine::init_vulkan()
- {
- vkb::InstanceBuilder builder;
- auto inst_ret = builder.set_app_name("Coral3D")
- .request_validation_layers(bUseValidationLayers)
- .use_default_debug_messenger()
- .require_api_version(1, 3, 0)
- .build();
- vkb::Instance vkb_inst = inst_ret.value();
- _instance = vkb_inst.instance;
- _debugMessenger = vkb_inst.debug_messenger;
- SDL_Vulkan_CreateSurface(_window, _instance, &_surface);
- //vulkan 1.3 features
- VkPhysicalDeviceVulkan13Features features{};
- features.dynamicRendering = true;
- features.synchronization2 = true;
- //vulkan 1.2 features
- VkPhysicalDeviceVulkan12Features features12{};
- features12.bufferDeviceAddress = true;
- features12.descriptorIndexing = true;
- //use vkbootstrap to select a gpu.
- //We want a gpu that can write to the SDL surface and supports vulkan 1.3 with the correct features
- vkb::PhysicalDeviceSelector selector{ vkb_inst };
- vkb::PhysicalDevice physicalDevice = selector
- .set_minimum_version(1, 3)
- .set_required_features_13(features)
- .set_required_features_12(features12)
- .set_surface(_surface)
- .select()
- .value();
- //create the final vulkan device
- vkb::DeviceBuilder deviceBuilder{ physicalDevice };
- vkb::Device vkbDevice = deviceBuilder.build().value();
- // Get the VkDevice handle used in the rest of a vulkan application
- _device = vkbDevice.device;
- _physicalGPU = physicalDevice.physical_device;
- _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)
- };
- // 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)};
- VK_CHECK(vkAllocateCommandBuffers(_device, &cmdAllocInfo, &frame._mainCommandBuffer));
- _mainDeletionQueue.push([=, this](){
- vkDestroyCommandPool(_device, frame._commandPool, nullptr);
- });
- }
- }
- void VulkanEngine::init_sync_structures()
- {
- // Fence is used to not record into cmd buffer that is being rendered
- // and 2 semaphores to synchronize rendering with swapchain.
- // Fence start signaled to be able to wait on it in the first frame.
- 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);
- });
- }
- }
- void VulkanEngine::create_swapchain(uint32_t width, uint32_t height)
- {
- vkb::SwapchainBuilder swapchainBuilder{ _physicalGPU,_device,_surface };
- _swapchainImageFormat = VK_FORMAT_B8G8R8A8_UNORM;
- vkb::Swapchain vkbSwapchain = swapchainBuilder
- .set_desired_format(VkSurfaceFormatKHR
- { .format = _swapchainImageFormat, .colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR })
- .set_desired_present_mode(VK_PRESENT_MODE_FIFO_KHR) // VSync present mode
- .set_desired_extent(width, height)
- .add_image_usage_flags(VK_IMAGE_USAGE_TRANSFER_DST_BIT)
- .build()
- .value();
- _swapchainExtent = vkbSwapchain.extent;
- // Store swapchain and its images
- _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::init_pipelines()
- {
- init_background_pipelines();
- }
- 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))
- {
- 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();
- });
- }
|