Skip to content

Commit

Permalink
Add imgui and performance graphs
Browse files Browse the repository at this point in the history
  • Loading branch information
shg8 committed Feb 18, 2024
1 parent 1301ffe commit 738178c
Show file tree
Hide file tree
Showing 19 changed files with 14,394 additions and 50 deletions.
60 changes: 60 additions & 0 deletions 3dgs/GUIManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "GUIManager.h"

#include <iostream>

static std::shared_ptr<std::unordered_map<std::string, ScrollingBuffer>> metricsMap;

GUIManager::GUIManager() {
metricsMap = std::make_shared<std::unordered_map<std::string, ScrollingBuffer>>();
}

void GUIManager::init() {
ImPlot::CreateContext();
}

void GUIManager::buildGui() {
ImGui::SetNextWindowSize(ImVec2(400, 250), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowPos(ImVec2(10, 10), ImGuiCond_FirstUseEver);
ImGui::Begin("Performance");

static float history = 10;

static ImPlotAxisFlags flags = ImPlotAxisFlags_AutoFit;
if (ImPlot::BeginPlot("##Scrolling", ImVec2(-1, -1))) {
ImPlot::SetupAxes("ms", "time", flags, flags);
const auto t = ImGui::GetTime();
ImPlot::SetupAxisLimits(ImAxis_X1, t - history, t, ImGuiCond_Always);
ImPlot::SetupAxisLimits(ImAxis_Y1, 0, 1);
ImPlot::SetNextFillStyle(IMPLOT_AUTO_COL, 0.5f);
for (auto& [name, values]: *metricsMap) {
if (!values.Data.empty()) {
ImPlot::PlotLine(name.c_str(), &values.Data[0].x, &values.Data[0].y, values.Data.size(), 0,
values.Offset, 2 * sizeof(float));
}
}
ImPlot::EndPlot();
}
ImGui::SliderFloat("History", &history, 1, 30, "%.1f s");
ImGui::End();

ImGui::SetNextWindowPos(ImVec2(10, 270), ImGuiCond_FirstUseEver);
ImGui::Begin("Controls");
ImGui::Text("WASD: Move");
ImGui::Text("Mouse: Look");
ImGui::End();

}

void GUIManager::pushMetric(const std::string& name, float value) {
int maxSize = 600;
if (!metricsMap->contains(name)) {
metricsMap->insert({name, ScrollingBuffer(maxSize)});
}
metricsMap->at(name).addPoint(ImGui::GetTime(), value / 1000000.0);
}

void GUIManager::pushMetric(const std::unordered_map<std::string, unsigned long long>& name) {
for (auto& [n, v]: name) {
pushMetric(n, v);
}
}
119 changes: 119 additions & 0 deletions 3dgs/GUIManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#ifndef GUIMANAGER_H
#define GUIMANAGER_H
#include <unordered_map>
#include <vector>
#include <string>


#include "imgui.h"
#include "implot/implot.h"

template<typename T>
class RingBuffer {
public:
explicit RingBuffer(size_t size = 600) : buffer(size), start(0), end(0), isFull(false) {}

void push(T value) {
buffer[end] = value;
end = (end + 1) % buffer.size();

if (isFull) {
start = (start + 1) % buffer.size();
}

isFull = end == start;
}

T pop() {
if (isEmpty()) {
throw std::runtime_error("Buffer is empty");
}

T value = buffer[start];
start = (start + 1) % buffer.size();
isFull = false;

return value;
}

bool isEmpty() const {
return !isFull && (end == start);
}

bool isBufferFull() const {
return isFull;
}

size_t capacity() const {
return buffer.size();
}

size_t size() const {
size_t size = buffer.size();

if (!isFull) {
if (end >= start) {
size = end - start;
} else {
size = buffer.size() + end - start;
}
}

return size;
}

T lookup(size_t index) const {
if (index >= size()) {
throw std::out_of_range("Index out of range");
}

return buffer[(start + index) % buffer.size()];
}

private:
std::vector<T> buffer;
size_t start;
size_t end;
bool isFull;
};

struct ScrollingBuffer {
int MaxSize;
int Offset;
ImVector<ImVec2> Data;
ScrollingBuffer(int max_size = 2000) {
MaxSize = max_size;
Offset = 0;
Data.reserve(MaxSize);
}
void addPoint(float x, float y) {
if (Data.size() < MaxSize)
Data.push_back(ImVec2(x,y));
else {
Data[Offset] = ImVec2(x,y);
Offset = (Offset + 1) % MaxSize;
}
}
void clear() {
if (Data.size() > 0) {
Data.shrink(0);
Offset = 0;
}
}
};

class GUIManager {
public:
GUIManager();

static void init();

static void buildGui();

static void pushMetric(const std::string& name, float value);

static void pushMetric(const std::unordered_map<std::string, unsigned long long>& name);

};

#endif //GUIMANAGER_H
45 changes: 41 additions & 4 deletions 3dgs/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

void Renderer::initialize() {
initializeVulkan();
createGui();
loadSceneToGPU();
createPreprocessPipeline();
createPrefixSumPipeline();
Expand Down Expand Up @@ -69,7 +70,7 @@ void Renderer::retrieveTimestamps() {
throw std::runtime_error("Failed to retrieve timestamps");
}

queryManager->parseResults(timestamps);
guiManager.pushMetric(queryManager->parseResults(timestamps));
}

void Renderer::initializeVulkan() {
Expand Down Expand Up @@ -110,6 +111,7 @@ void Renderer::initializeVulkan() {
void Renderer::loadSceneToGPU() {
scene = std::make_shared<GSScene>(configuration.scene);
scene->load(context);

// reset descriptor pool
context->device->resetDescriptorPool(context->descriptorPool.get());
}
Expand Down Expand Up @@ -147,6 +149,16 @@ void Renderer::createPreprocessPipeline() {
Renderer::Renderer(RendererConfiguration configuration) : configuration(std::move(configuration)) {
}

void Renderer::createGui() {
if (!configuration.enableGui) {
return;
}

imguiManager = std::make_shared<ImguiManager>(context, swapchain, window);
imguiManager->init();
guiManager.init();
}

void Renderer::createPrefixSumPipeline() {
prefixSumPingBuffer = Buffer::storage(context, scene->getNumVertices() * sizeof(uint32_t), false);
prefixSumPongBuffer = Buffer::storage(context, scene->getNumVertices() * sizeof(uint32_t), false);
Expand Down Expand Up @@ -399,6 +411,8 @@ void Renderer::recordPreprocessCommandBuffer() {

preprocessCommandBuffer->begin(vk::CommandBufferBeginInfo{});

preprocessCommandBuffer->resetQueryPool(context->queryPool.get(), 0, 12);

preprocessPipeline->bind(preprocessCommandBuffer, 0, 0);
preprocessCommandBuffer->writeTimestamp(vk::PipelineStageFlagBits::eTopOfPipe, context->queryPool.get(), queryManager->registerQuery("preprocess_start"));
preprocessCommandBuffer->dispatch(numGroups, 1, 1);
Expand Down Expand Up @@ -560,15 +574,38 @@ void Renderer::recordRenderCommandBuffer(uint32_t currentFrame) {

// image layout transition: general -> present
imageMemoryBarrier.oldLayout = vk::ImageLayout::eGeneral;
imageMemoryBarrier.newLayout = vk::ImageLayout::ePresentSrcKHR;
imageMemoryBarrier.srcAccessMask = vk::AccessFlagBits::eShaderWrite;
imageMemoryBarrier.dstAccessMask = vk::AccessFlagBits::eMemoryRead;
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
renderCommandBuffer->pipelineBarrier(vk::PipelineStageFlagBits::eComputeShader,

if (configuration.enableGui) {
imageMemoryBarrier.newLayout = vk::ImageLayout::eColorAttachmentOptimal;
imageMemoryBarrier.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite;
renderCommandBuffer->pipelineBarrier(vk::PipelineStageFlagBits::eComputeShader,
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::DependencyFlagBits::eByRegion, nullptr, nullptr, imageMemoryBarrier);
} else {
imageMemoryBarrier.newLayout = vk::ImageLayout::ePresentSrcKHR;
imageMemoryBarrier.dstAccessMask = vk::AccessFlagBits::eMemoryRead;
renderCommandBuffer->pipelineBarrier(vk::PipelineStageFlagBits::eComputeShader,
vk::PipelineStageFlagBits::eBottomOfPipe,
vk::DependencyFlagBits::eByRegion, nullptr, nullptr, imageMemoryBarrier);
}
renderCommandBuffer->writeTimestamp(vk::PipelineStageFlagBits::eBottomOfPipe, context->queryPool.get(), queryManager->registerQuery("render_end"));

if (configuration.enableGui) {
imguiManager->draw(renderCommandBuffer.get(), currentImageIndex, &GUIManager::buildGui);

imageMemoryBarrier.oldLayout = vk::ImageLayout::eColorAttachmentOptimal;
imageMemoryBarrier.srcAccessMask = vk::AccessFlagBits::eColorAttachmentWrite;

imageMemoryBarrier.newLayout = vk::ImageLayout::ePresentSrcKHR;
imageMemoryBarrier.dstAccessMask = vk::AccessFlagBits::eMemoryRead;

renderCommandBuffer->pipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eBottomOfPipe,
vk::DependencyFlagBits::eByRegion, nullptr, nullptr, imageMemoryBarrier);
}
renderCommandBuffer->end();
}

Expand Down
9 changes: 8 additions & 1 deletion 3dgs/Renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#define GLM_SWIZZLE

#include <args.hxx>
#include <atomic>

#include "../vulkan/Window.h"
Expand All @@ -11,6 +12,8 @@
#include "../vulkan/Swapchain.h"
#include <glm/gtc/quaternion.hpp>

#include "GUIManager.h"
#include "../vulkan/ImguiManager.h"
#include "../vulkan/QueryManager.h"

struct RendererConfiguration {
Expand All @@ -22,6 +25,7 @@ struct RendererConfiguration {
float fov = 45.0f;
float near = 0.2f;
float far = 1000.0f;
bool enableGui = true;
};

class Renderer {
Expand Down Expand Up @@ -62,6 +66,8 @@ class Renderer {

explicit Renderer(RendererConfiguration configuration);

void createGui();

void initialize();

void handleInput();
Expand All @@ -75,8 +81,10 @@ class Renderer {
RendererConfiguration configuration;
std::shared_ptr<Window> window;
std::shared_ptr<VulkanContext> context;
std::shared_ptr<ImguiManager> imguiManager;
std::shared_ptr<GSScene> scene;
std::shared_ptr<QueryManager> queryManager = std::make_shared<QueryManager>();
GUIManager guiManager {};

std::shared_ptr<ComputePipeline> preprocessPipeline;
std::shared_ptr<ComputePipeline> renderPipeline;
Expand Down Expand Up @@ -107,7 +115,6 @@ class Renderer {

std::shared_ptr<Swapchain> swapchain;


Camera camera {
.position = glm::vec3(0.0f, 0.0f, 0.0f),
.rotation = glm::quat(1.0f, 0.0f, 0.0f, 0.0f),
Expand Down
28 changes: 27 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ FetchContent_Declare(libenvpp
)
FetchContent_MakeAvailable(libenvpp)

FetchContent_Declare(imgui
GIT_REPOSITORY https://github.com/ocornut/imgui.git
GIT_TAG v1.90.3
)
FetchContent_MakeAvailable(imgui)

if (APPLE)
add_compile_definitions(__APPLE__)
endif ()
Expand Down Expand Up @@ -95,6 +101,15 @@ add_custom_target(

include_directories(third_party)

file(GLOB EXTERNAL_SOURCE
${imgui_SOURCE_DIR}/*.cpp
${imgui_SOURCE_DIR}/backends/imgui_impl_glfw.cpp
${imgui_SOURCE_DIR}/backends/imgui_impl_vulkan.cpp
third_party/implot/implot.cpp
third_party/implot/implot_demo.cpp
third_party/implot/implot_items.cpp
)

add_executable(vulkan_splatting main.cpp
vulkan/VulkanContext.cpp
3dgs/Renderer.cpp
Expand All @@ -113,13 +128,24 @@ add_executable(vulkan_splatting main.cpp
vulkan/pipelines/ComputePipeline.h
vulkan/Swapchain.cpp
vulkan/Swapchain.h
${EXTERNAL_SOURCE}
vulkan/ImguiManager.cpp
vulkan/ImguiManager.h
vulkan/QueryManager.cpp
vulkan/QueryManager.h
3dgs/GUIManager.cpp
3dgs/GUIManager.h
)

add_dependencies(vulkan_splatting Shaders)

target_include_directories(vulkan_splatting PUBLIC ${Vulkan_INCLUDE_DIRS} ${GLM_INCLUDE_DIRS} ${glm_SOURCE_DIR})
target_include_directories(vulkan_splatting PUBLIC
${Vulkan_INCLUDE_DIRS}
${GLM_INCLUDE_DIRS}
${glm_SOURCE_DIR}
${imgui_SOURCE_DIR}
${imgui_SOURCE_DIR}/backends
)

target_link_libraries(vulkan_splatting PUBLIC glfw libenvpp::libenvpp)
target_link_libraries(vulkan_splatting PUBLIC Vulkan::Vulkan)
Expand Down
Loading

0 comments on commit 738178c

Please sign in to comment.