ImGui integration.

This commit is contained in:
Anish Bhobe 2024-07-23 20:48:55 +02:00
parent b356991cad
commit 4dd8effd7b
8 changed files with 300 additions and 10 deletions

View File

@ -9,19 +9,18 @@ A Vulkan based renderer created with Vulkan 1.3 in C++.
- [X] Load Material Data - [X] Load Material Data
- [ ] Load Animation Data - [ ] Load Animation Data
- [ ] Load Camera - [ ] Load Camera
- [ ] Load Lights
- [ ] Support Specular Materials - [ ] Support Specular Materials
- [X] Bindless Descriptors - [X] Bindless Descriptors
- [X] Simplified Descriptor Creation Pipeline - [X] Simplified Descriptor Creation Pipeline
- [ ] Debugging - [ ] Debugging
- [ ] Tracy Integration - [ ] Tracy Integration
- [ ] Dear ImGui Integration - [X] Dear ImGui Integration
- [ ] Transparency - [ ] Transparency
- [ ] Sorted - [ ] Sorted
- [ ] Order Independent - [ ] Order Independent
- [ ] Shadows v1 - [ ] Shadows v1
- [ ] Omnidirectional Cubemap Shadows - [ ] Omnidirectional Cubemap Shadows
- [ ] Spot Lights - [ ] SpotLight Shadows
- [ ] Directional Shadows - [ ] Directional Shadows
- [ ] Cascaded Shadows - [ ] Cascaded Shadows
- [ ] PCF - [ ] PCF

View File

@ -8,6 +8,12 @@
#include "context.h" #include "context.h"
#include "logger.h" #include "logger.h"
void
Window::RequestExit() const noexcept
{
glfwSetWindowShouldClose(m_Window, true);
}
void void
Window::SetWindowSize(const vk::Extent2D &extent) const noexcept Window::SetWindowSize(const vk::Extent2D &extent) const noexcept
{ {

View File

@ -27,6 +27,7 @@ struct Window final
return !glfwWindowShouldClose(m_Window); return !glfwWindowShouldClose(m_Window);
} }
void RequestExit() const noexcept;
void SetWindowSize(const vk::Extent2D &extent) const noexcept; void SetWindowSize(const vk::Extent2D &extent) const noexcept;
void SetWindowSize(u32 width, u32 height) const noexcept; void SetWindowSize(u32 width, u32 height) const noexcept;
/// Actual size of the framebuffer being used for the window render. /// Actual size of the framebuffer being used for the window render.

View File

@ -2,13 +2,18 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
find_package(imgui CONFIG REQUIRED)
add_library(util_helper STATIC add_library(util_helper STATIC
helpers.h helpers.h
helpers.cpp helpers.cpp
frame.cpp frame.cpp
frame.h frame.h
gpu_resource_manager.cpp gpu_resource_manager.cpp
gpu_resource_manager.h) gpu_resource_manager.h
gui.cpp
gui.h)
target_link_libraries(util_helper PRIVATE aster_core) target_link_libraries(util_helper PRIVATE aster_core)
target_link_libraries(util_helper PRIVATE imgui::imgui)
target_include_directories(util_helper PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(util_helper PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

213
samples/00_util/gui.cpp Normal file
View File

@ -0,0 +1,213 @@
// =============================================
// Aster: gui.cpp
// Copyright (c) 2020-2024 Anish Bhobe
// =============================================
#include "gui.h"
#include "context.h"
#include "device.h"
#include "helpers.h"
#include "image.h"
#include "window.h"
#include <imgui_impl_glfw.h>
#include <imgui_impl_vulkan.h>
#include <imgui_internal.h>
namespace ImGui
{
vk::Format g_AttachmentFormat;
vk::DescriptorPool g_DescriptorPool;
void
VulkanAssert(VkResult result)
{
AbortIfFailed(result);
}
void
Init(const Context *context, const Device *device, const Window *window, vk::Format attachmentFormat,
const u32 imageCount, const u32 queueFamily, const vk::Queue queue)
{
g_AttachmentFormat = attachmentFormat;
eastl::vector<vk::DescriptorPoolSize> poolSizes = {
{vk::DescriptorType::eSampler, 1000},
{vk::DescriptorType::eCombinedImageSampler, 1000},
{vk::DescriptorType::eSampledImage, 1000},
{vk::DescriptorType::eStorageImage, 1000},
{vk::DescriptorType::eUniformTexelBuffer, 1000},
{vk::DescriptorType::eStorageTexelBuffer, 1000},
{vk::DescriptorType::eUniformBuffer, 1000},
{vk::DescriptorType::eStorageBuffer, 1000},
{vk::DescriptorType::eUniformBufferDynamic, 1000},
{vk::DescriptorType::eStorageBufferDynamic, 1000},
{vk::DescriptorType::eInputAttachment, 1000},
};
const vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {
.flags = vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
.maxSets = 1000,
.poolSizeCount = Cast<u32>(poolSizes.size()),
.pPoolSizes = poolSizes.data(),
};
AbortIfFailed(device->m_Device.createDescriptorPool(&descriptorPoolCreateInfo, nullptr, &g_DescriptorPool));
IMGUI_CHECKVERSION();
CreateContext();
ImGuiIO &io = GetIO();
(void)io;
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
// io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Viewports bad
StyleColorsDark();
ImGui_ImplGlfw_InitForVulkan(window->m_Window, true);
vk::PipelineRenderingCreateInfo renderingCreateInfo = {
.colorAttachmentCount = 1,
.pColorAttachmentFormats = &g_AttachmentFormat,
};
ImGui_ImplVulkan_InitInfo imguiVulkanInitInfo = {
.Instance = context->m_Instance,
.PhysicalDevice = device->m_PhysicalDevice,
.Device = device->m_Device,
.QueueFamily = queueFamily,
.Queue = queue,
.DescriptorPool = g_DescriptorPool,
.MinImageCount = imageCount,
.ImageCount = imageCount,
.PipelineCache = nullptr,
.UseDynamicRendering = true,
.PipelineRenderingCreateInfo = renderingCreateInfo,
.Allocator = nullptr,
.CheckVkResultFn = VulkanAssert,
};
ImGui_ImplVulkan_Init(&imguiVulkanInitInfo);
ImGui_ImplVulkan_CreateFontsTexture();
}
void
Destroy(const Device *device)
{
ImGui_ImplVulkan_Shutdown();
ImGui_ImplGlfw_Shutdown();
DestroyContext();
device->m_Device.destroy(Take(g_DescriptorPool), nullptr);
}
void
StartBuild()
{
ImGui_ImplVulkan_NewFrame();
ImGui_ImplGlfw_NewFrame();
NewFrame();
static ImGuiDockNodeFlags dockspaceFlags = ImGuiDockNodeFlags_None | ImGuiDockNodeFlags_PassthruCentralNode;
// We are using the ImGuiWindowFlags_NoDocking flag to make the parent window not dockable into,
// because it would be confusing to have two docking targets within each others.
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_NoDocking;
const ImGuiViewport *viewport = GetMainViewport();
SetNextWindowPos(viewport->WorkPos);
SetNextWindowSize(viewport->WorkSize);
SetNextWindowViewport(viewport->ID);
PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
windowFlags |=
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
windowFlags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
windowFlags |= ImGuiWindowFlags_NoBackground;
// Important: note that we proceed even if Begin() returns false (aka window is collapsed).
// This is because we want to keep our DockSpace() active. If a DockSpace() is inactive,
// all active windows docked into it will lose their parent and become undocked.
// We cannot preserve the docking relationship between an active window and an inactive docking, otherwise
// any change of dockspace/settings would lead to windows being stuck in limbo and never being visible.
PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
Begin("DockSpace Demo", nullptr, windowFlags);
PopStyleVar();
PopStyleVar(2);
// DockSpace
if (GetIO().ConfigFlags & ImGuiConfigFlags_DockingEnable)
{
const ImGuiID dockspaceId = GetID("MyDockSpace");
DockSpace(dockspaceId, ImVec2(0.0f, 0.0f), dockspaceFlags);
}
}
void
EndBuild()
{
End();
Render();
EndFrame();
if (GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
GLFWwindow *backupCurrentContext = glfwGetCurrentContext();
UpdatePlatformWindows();
RenderPlatformWindowsDefault();
glfwMakeContextCurrent(backupCurrentContext);
}
}
void
Draw(const vk::CommandBuffer commandBuffer, const AttachmentImage *attachmentImage)
{
// OPTICK_EVENT();
constexpr vk::DebugUtilsLabelEXT label = {
.pLabelName = "UI pass",
.color = std::array{0.0f, 0.0f, 1.0f, 1.0f},
};
commandBuffer.beginDebugUtilsLabelEXT(&label);
vk::RenderingAttachmentInfo attachmentInfo = {
.imageView = attachmentImage->m_View,
.imageLayout = vk::ImageLayout::eColorAttachmentOptimal,
.resolveMode = vk::ResolveModeFlagBits::eNone,
.loadOp = vk::AttachmentLoadOp::eLoad,
.storeOp = vk::AttachmentStoreOp::eStore,
.clearValue = vk::ClearColorValue{0.0f, 0.0f, 0.0f, 1.0f},
};
const vk::RenderingInfo renderingInfo = {
.renderArea = {.extent = ToExtent2D(attachmentImage->m_Extent)},
.layerCount = 1,
.colorAttachmentCount = 1,
.pColorAttachments = &attachmentInfo,
.pDepthAttachment = nullptr,
};
commandBuffer.beginRendering(&renderingInfo);
ImGui_ImplVulkan_RenderDrawData(GetDrawData(), commandBuffer);
commandBuffer.endRendering();
commandBuffer.endDebugUtilsLabelEXT();
}
void
PushDisable()
{
PushItemFlag(ImGuiItemFlags_Disabled, true);
PushStyleVar(ImGuiStyleVar_Alpha, GetStyle().Alpha * 0.5f);
}
void
PopDisable()
{
PopStyleVar();
PopItemFlag();
}
} // namespace ImGui

34
samples/00_util/gui.h Normal file
View File

@ -0,0 +1,34 @@
// =============================================
// Aster: gui.h
// Copyright (c) 2020-2024 Anish Bhobe
// =============================================
#pragma once
#include "global.h"
#include <imgui.h>
struct AttachmentImage;
struct Device;
struct Context;
struct Window;
struct Swapchain;
// ReSharper disable once CppInconsistentNaming
namespace ImGui
{
void Init(const Context *context, const Device *device, const Window *window, vk::Format attachmentFormat,
u32 imageCount, u32 queueFamily, vk::Queue queue);
void Destroy(const Device *device);
void Recreate();
void StartBuild();
void EndBuild();
void Draw(vk::CommandBuffer commandBuffer, const AttachmentImage *attachmentImage);
void PushDisable();
void PopDisable();
} // namespace ImGui
namespace gui = ImGui;

View File

@ -19,6 +19,7 @@
#include "light_manager.h" #include "light_manager.h"
#include "gpu_resource_manager.h" #include "gpu_resource_manager.h"
#include "gui.h"
#include "model_loader.h" #include "model_loader.h"
#include "pipeline_utils.h" #include "pipeline_utils.h"
@ -214,6 +215,10 @@ main(int, char **)
} }
} }
gui::Init(&context, &device, &window, attachmentFormat, frameManager.m_FramesInFlight, queueAllocation.m_Family,
commandQueue);
bool rotating = false;
Time::Init(); Time::Init();
INFO("Starting loop"); INFO("Starting loop");
@ -221,8 +226,25 @@ main(int, char **)
{ {
Time::Update(); Time::Update();
gui::StartBuild();
gui::Begin("Settings");
gui::Text("Delta: %0.6f ms", 1000.0f * Time::m_Delta);
gui::Text("FPS: %0.6f", 1.0f / Time::m_Delta);
gui::Checkbox("Rotate", &rotating);
if (gui::Button("Exit"))
{
window.RequestExit();
}
gui::End();
gui::EndBuild();
if (rotating)
{
model.SetModelTransform( model.SetModelTransform(
rotate(model.GetModelTransform(), Cast<f32>(45.0_deg * Time::m_Delta), vec3(0.0f, 1.0f, 0.0f))); rotate(model.GetModelTransform(), Cast<f32>(45.0_deg * Time::m_Delta), vec3(0.0f, 1.0f, 0.0f)));
}
model.Update(); model.Update();
ubo.Write(&device, 0, sizeof camera, &camera); ubo.Write(&device, 0, sizeof camera, &camera);
@ -300,18 +322,18 @@ main(int, char **)
{ {
u32 innerPcbOffset = pcbOffset; u32 innerPcbOffset = pcbOffset;
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, innerPcbOffset, cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, innerPcbOffset,
sizeof prim.m_MaterialIdx, sizeof prim.m_MaterialIdx, &prim.m_MaterialIdx);
&prim.m_MaterialIdx);
innerPcbOffset += sizeof prim.m_MaterialIdx; innerPcbOffset += sizeof prim.m_MaterialIdx;
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, innerPcbOffset, cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, innerPcbOffset,
sizeof prim.m_TransformIdx, sizeof prim.m_TransformIdx, &prim.m_TransformIdx);
&prim.m_TransformIdx);
innerPcbOffset += sizeof prim.m_TransformIdx; innerPcbOffset += sizeof prim.m_TransformIdx;
cmd.drawIndexed(prim.m_IndexCount, 1, prim.m_FirstIndex, Cast<i32>(prim.m_VertexOffset), 0); cmd.drawIndexed(prim.m_IndexCount, 1, prim.m_FirstIndex, Cast<i32>(prim.m_VertexOffset), 0);
} }
cmd.endRendering(); cmd.endRendering();
gui::Draw(cmd, currentAttachment);
cmd.pipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eAllCommands, cmd.pipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eAllCommands,
{}, 0, nullptr, 0, nullptr, postRenderBarriers.size(), postRenderBarriers.data()); {}, 0, nullptr, 0, nullptr, postRenderBarriers.size(), postRenderBarriers.data());
@ -366,6 +388,8 @@ main(int, char **)
AbortIfFailed(device.m_Device.waitIdle()); AbortIfFailed(device.m_Device.waitIdle());
gui::Destroy(&device);
for (auto &depthImage : depthImages) for (auto &depthImage : depthImages)
{ {
depthImage.Destroy(&device); depthImage.Destroy(&device);

View File

@ -4,6 +4,14 @@
"fmt", "fmt",
"glfw3", "glfw3",
"glm", "glm",
{
"name": "imgui",
"features": [
"glfw-binding",
"vulkan-binding",
"docking-experimental"
]
},
"scottt-debugbreak", "scottt-debugbreak",
"tinygltf", "tinygltf",
"vulkan-memory-allocator" "vulkan-memory-allocator"