ImGui integration.
This commit is contained in:
parent
b356991cad
commit
4dd8effd7b
|
|
@ -9,19 +9,18 @@ A Vulkan based renderer created with Vulkan 1.3 in C++.
|
|||
- [X] Load Material Data
|
||||
- [ ] Load Animation Data
|
||||
- [ ] Load Camera
|
||||
- [ ] Load Lights
|
||||
- [ ] Support Specular Materials
|
||||
- [X] Bindless Descriptors
|
||||
- [X] Simplified Descriptor Creation Pipeline
|
||||
- [ ] Debugging
|
||||
- [ ] Tracy Integration
|
||||
- [ ] Dear ImGui Integration
|
||||
- [X] Dear ImGui Integration
|
||||
- [ ] Transparency
|
||||
- [ ] Sorted
|
||||
- [ ] Order Independent
|
||||
- [ ] Shadows v1
|
||||
- [ ] Omnidirectional Cubemap Shadows
|
||||
- [ ] Spot Lights
|
||||
- [ ] SpotLight Shadows
|
||||
- [ ] Directional Shadows
|
||||
- [ ] Cascaded Shadows
|
||||
- [ ] PCF
|
||||
|
|
|
|||
|
|
@ -8,6 +8,12 @@
|
|||
#include "context.h"
|
||||
#include "logger.h"
|
||||
|
||||
void
|
||||
Window::RequestExit() const noexcept
|
||||
{
|
||||
glfwSetWindowShouldClose(m_Window, true);
|
||||
}
|
||||
|
||||
void
|
||||
Window::SetWindowSize(const vk::Extent2D &extent) const noexcept
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ struct Window final
|
|||
return !glfwWindowShouldClose(m_Window);
|
||||
}
|
||||
|
||||
void RequestExit() const noexcept;
|
||||
void SetWindowSize(const vk::Extent2D &extent) const noexcept;
|
||||
void SetWindowSize(u32 width, u32 height) const noexcept;
|
||||
/// Actual size of the framebuffer being used for the window render.
|
||||
|
|
|
|||
|
|
@ -2,13 +2,18 @@
|
|||
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
find_package(imgui CONFIG REQUIRED)
|
||||
|
||||
add_library(util_helper STATIC
|
||||
helpers.h
|
||||
helpers.cpp
|
||||
frame.cpp
|
||||
frame.h
|
||||
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 imgui::imgui)
|
||||
target_include_directories(util_helper PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
#include "light_manager.h"
|
||||
|
||||
#include "gpu_resource_manager.h"
|
||||
#include "gui.h"
|
||||
#include "model_loader.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();
|
||||
|
||||
INFO("Starting loop");
|
||||
|
|
@ -221,8 +226,25 @@ main(int, char **)
|
|||
{
|
||||
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(
|
||||
rotate(model.GetModelTransform(), Cast<f32>(45.0_deg * Time::m_Delta), vec3(0.0f, 1.0f, 0.0f)));
|
||||
}
|
||||
model.Update();
|
||||
ubo.Write(&device, 0, sizeof camera, &camera);
|
||||
|
||||
|
|
@ -300,18 +322,18 @@ main(int, char **)
|
|||
{
|
||||
u32 innerPcbOffset = pcbOffset;
|
||||
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, innerPcbOffset,
|
||||
sizeof prim.m_MaterialIdx,
|
||||
&prim.m_MaterialIdx);
|
||||
sizeof prim.m_MaterialIdx, &prim.m_MaterialIdx);
|
||||
innerPcbOffset += sizeof prim.m_MaterialIdx;
|
||||
cmd.pushConstants(pipeline.m_Layout, vk::ShaderStageFlagBits::eAll, innerPcbOffset,
|
||||
sizeof prim.m_TransformIdx,
|
||||
&prim.m_TransformIdx);
|
||||
sizeof prim.m_TransformIdx, &prim.m_TransformIdx);
|
||||
innerPcbOffset += sizeof prim.m_TransformIdx;
|
||||
cmd.drawIndexed(prim.m_IndexCount, 1, prim.m_FirstIndex, Cast<i32>(prim.m_VertexOffset), 0);
|
||||
}
|
||||
|
||||
cmd.endRendering();
|
||||
|
||||
gui::Draw(cmd, currentAttachment);
|
||||
|
||||
cmd.pipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput, vk::PipelineStageFlagBits::eAllCommands,
|
||||
{}, 0, nullptr, 0, nullptr, postRenderBarriers.size(), postRenderBarriers.data());
|
||||
|
||||
|
|
@ -366,6 +388,8 @@ main(int, char **)
|
|||
|
||||
AbortIfFailed(device.m_Device.waitIdle());
|
||||
|
||||
gui::Destroy(&device);
|
||||
|
||||
for (auto &depthImage : depthImages)
|
||||
{
|
||||
depthImage.Destroy(&device);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,14 @@
|
|||
"fmt",
|
||||
"glfw3",
|
||||
"glm",
|
||||
{
|
||||
"name": "imgui",
|
||||
"features": [
|
||||
"glfw-binding",
|
||||
"vulkan-binding",
|
||||
"docking-experimental"
|
||||
]
|
||||
},
|
||||
"scottt-debugbreak",
|
||||
"tinygltf",
|
||||
"vulkan-memory-allocator"
|
||||
|
|
|
|||
Loading…
Reference in New Issue