ImGUI is now working in the program.

This commit is contained in:
Zed A. Shaw 2025-12-01 23:53:16 -05:00
parent fe79797313
commit 14f307b1b3
5 changed files with 190 additions and 7 deletions

View file

@ -70,7 +70,14 @@ endif
vma = subproject('vulkan-memory-allocator').get_variable('vma_allocator_dep')
# vulkan_headers = subproject('vulkan-headers').get_variable('vulkan_headers_dep')
imgui = subproject('imgui').get_variable('imgui_dep')
imgui = subproject('imgui',
default_options: {
'vulkan': 'enabled',
'sdl2_renderer': 'enabled'
},
).get_variable('imgui_dep')
sdl2 = subproject('sdl2').get_variable('sdl2_dep')

View file

@ -12,11 +12,14 @@
#include <chrono>
#include <thread>
#include "imgui.h"
#include "imgui_impl_sdl2.h"
#include "imgui_impl_vulkan.h"
#define VMA_IMPLEMENTATION
#include "vk_mem_alloc.h"
constexpr bool bUseValidationLayers = true;
constexpr bool bUseValidationLayers = false;
VulkanEngine* loadedEngine = nullptr;
@ -48,6 +51,7 @@ void VulkanEngine::init()
init_sync_structures();
init_descriptors();
init_pipelines();
init_imgui();
//everything went fine
_isInitialized = true;
@ -119,6 +123,10 @@ void VulkanEngine::draw()
_swapchainImages[swapchainImageIndex],
_drawExtent, _swapchainExtent);
vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
draw_imgui(cmd, _swapchainImageViews[swapchainImageIndex]);
vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
VK_CHECK(vkEndCommandBuffer(cmd));
@ -142,7 +150,7 @@ void VulkanEngine::draw()
// this will put the image we just rendered to into the visible window.
// we want to wait on the _renderSemaphore for that,
// as its necessary that drawing commands have finished before the image is displayed to the user
VkPresentInfoKHR presentInfo = {};
VkPresentInfoKHR presentInfo{};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.pNext = nullptr;
presentInfo.pSwapchains = &_swapchain;
@ -185,6 +193,8 @@ void VulkanEngine::run()
stop_rendering = false;
}
}
ImGui_ImplSDL2_ProcessEvent(&e);
}
if(stop_rendering) {
@ -192,6 +202,13 @@ void VulkanEngine::run()
continue;
}
ImGui_ImplVulkan_NewFrame();
ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame();
ImGui::ShowDemoWindow();
ImGui::Render();
draw();
}
}
@ -345,6 +362,16 @@ void VulkanEngine::init_commands() {
VK_CHECK(vkAllocateCommandBuffers(_device, &cmdAllocInfo, &_frames[i]._mainCommandBuffer));
}
VK_CHECK(vkCreateCommandPool(_device, &commandPoolInfo, nullptr, &_immCommandPool));
VkCommandBufferAllocateInfo cmdAllocInfo = vkinit::command_buffer_allocate_info(_immCommandPool, 1);
VK_CHECK(vkAllocateCommandBuffers(_device, &cmdAllocInfo, &_immCommandBuffer));
_mainDeletionQueue.push_function([=,this]() {
vkDestroyCommandPool(_device, _immCommandPool, nullptr);
});
}
void VulkanEngine::init_sync_structures() {
@ -357,6 +384,12 @@ void VulkanEngine::init_sync_structures() {
VK_CHECK(vkCreateSemaphore(_device, &semaphoreCreateInfo, nullptr, &_frames[i]._swapchainSemaphore));
VK_CHECK(vkCreateSemaphore(_device, &semaphoreCreateInfo, nullptr, &_frames[i]._renderSemaphore));
}
VK_CHECK(vkCreateFence(_device, &fenceCreateInfo, nullptr, &_immFence));
_mainDeletionQueue.push_function([=,this]() {
vkDestroyFence(_device, _immFence, nullptr);
});
}
void VulkanEngine::draw_background(VkCommandBuffer cmd)
@ -405,7 +438,7 @@ void VulkanEngine::init_descriptors() {
drawImageWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
drawImageWrite.pImageInfo = &imgInfo;
vkUpdateDescriptorSets(_device, 1, &drawImageWrite, 0, nullptr);
vkUpdateDescriptorSets(_device, 1, &drawImageWrite, 0, nullptr),
//make sure both the descriptor allocator and the new layout get cleaned up properly
_mainDeletionQueue.push_function([&]() {
@ -458,3 +491,97 @@ void VulkanEngine::init_background_pipelines()
vkDestroyPipeline(_device, _gradientPipeline, nullptr);
});
}
void VulkanEngine::immediate_submit(std::function<void(VkCommandBuffer cmd)>&& function)
{
VK_CHECK(vkResetFences(_device, 1, &_immFence));
VK_CHECK(vkResetCommandBuffer(_immCommandBuffer, 0));
VkCommandBuffer cmd = _immCommandBuffer;
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);
VK_CHECK(vkQueueSubmit2(_graphicsQueue, 1, &submit, _immFence));
VK_CHECK(vkWaitForFences(_device, 1, &_immFence, true,9999999999));
}
void VulkanEngine::init_imgui()
{
// 1: create descriptor pool for IMGUI
// the size of the pool is very oversize, but it's copied from imgui demo
// itself.
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));
// 2: initialize the imgui library
ImGui::CreateContext();
ImGui_ImplSDL2_InitForVulkan(_window);
ImGui_ImplVulkan_InitInfo init_info{};
init_info.Instance = _instance;
init_info.PhysicalDevice = _chosenGPU;
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.PipelineRenderingCreateInfo = {.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO};
init_info.PipelineRenderingCreateInfo.colorAttachmentCount = 1;
init_info.PipelineRenderingCreateInfo.pColorAttachmentFormats = &_swapchainImageFormat;
init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
ImGui_ImplVulkan_Init(&init_info);
ImGui_ImplVulkan_CreateFontsTexture();
_mainDeletionQueue.push_function([=,this]() {
ImGui_ImplVulkan_Shutdown();
vkDestroyDescriptorPool(_device, imguiPool, nullptr);
});
}
void VulkanEngine::draw_imgui(VkCommandBuffer cmd, VkImageView targetImageView)
{
VkRenderingAttachmentInfo colorAttachment = vkinit::attachment_info(targetImageView, nullptr, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
VkRenderingInfo renderInfo = vkinit::rendering_info(_swapchainExtent, &colorAttachment, nullptr);
vkCmdBeginRendering(cmd, &renderInfo);
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd);
vkCmdEndRendering(cmd);
}

View file

@ -36,6 +36,9 @@ constexpr unsigned int FRAME_OVERLAP=2;
class VulkanEngine {
public:
VkFence _immFence;
VkCommandBuffer _immCommandBuffer;
VkCommandPool _immCommandPool;
VkPipeline _gradientPipeline;
VkPipelineLayout _gradientPipelineLayout;
@ -96,6 +99,8 @@ public:
//run main loop
void run();
void immediate_submit(std::function<void(VkCommandBuffer cmd)>&& function);
private:
void init_vulkan();
void init_swapchain();
@ -104,8 +109,10 @@ private:
void init_descriptors();
void init_pipelines();
void init_background_pipelines();
void init_imgui();
void create_swapchain(uint32_t width, uint32_t height);
void destroy_swapchain();
void draw_background(VkCommandBuffer cmd);
void draw_imgui(VkCommandBuffer cmd, VkImageView targetImageView);
};

View file

@ -148,3 +148,40 @@ VkImageViewCreateInfo vkinit::imageview_create_info(VkFormat format, VkImage ima
return info;
}
VkRenderingAttachmentInfo vkinit::attachment_info(
VkImageView view, VkClearValue* clear ,VkImageLayout layout /*= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL*/)
{
VkRenderingAttachmentInfo colorAttachment {};
colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
colorAttachment.pNext = nullptr;
colorAttachment.imageView = view;
colorAttachment.imageLayout = layout;
colorAttachment.loadOp = clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
if (clear) {
colorAttachment.clearValue = *clear;
}
return colorAttachment;
}
VkRenderingInfo vkinit::rendering_info(VkExtent2D renderExtent, VkRenderingAttachmentInfo* colorAttachment,
VkRenderingAttachmentInfo* depthAttachment)
{
VkRenderingInfo renderInfo {};
renderInfo.sType = VK_STRUCTURE_TYPE_RENDERING_INFO;
renderInfo.pNext = nullptr;
renderInfo.renderArea = VkRect2D { VkOffset2D { 0, 0 }, renderExtent };
renderInfo.layerCount = 1;
renderInfo.colorAttachmentCount = 1;
renderInfo.pColorAttachments = colorAttachment;
renderInfo.pDepthAttachment = depthAttachment;
renderInfo.pStencilAttachment = nullptr;
return renderInfo;
}

View file

@ -30,5 +30,10 @@ namespace vkinit {
VkImageViewCreateInfo imageview_create_info(VkFormat format, VkImage image, VkImageAspectFlags aspectFlags);
VkImageCreateInfo image_create_info(VkFormat format, VkImageUsageFlags usageFlags, VkExtent3D extent);
VkRenderingAttachmentInfo attachment_info(
VkImageView view, VkClearValue* clear ,VkImageLayout layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
VkRenderingInfo rendering_info(VkExtent2D renderExtent, VkRenderingAttachmentInfo* colorAttachment, VkRenderingAttachmentInfo* depthAttachment);
}