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
|
- [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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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})
|
||||||
|
|
|
||||||
|
|
@ -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 "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();
|
||||||
|
|
||||||
model.SetModelTransform(
|
gui::StartBuild();
|
||||||
rotate(model.GetModelTransform(), Cast<f32>(45.0_deg * Time::m_Delta), vec3(0.0f, 1.0f, 0.0f)));
|
|
||||||
|
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();
|
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);
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue