add imgui as submodule, different double buffering for computing

feature/softbody-runtime-control
Benjamin Kraft 3 months ago
parent fc85eca7a7
commit 47e5367219
  1. 4
      .gitmodules
  2. 8
      CMakeLists.txt
  3. 27
      imgui.ini
  4. 1
      include/application.hpp
  5. 2
      include/vulkan/descriptor_pool.hpp
  6. 7
      include/vulkan/instance.hpp
  7. 1
      lib/imgui
  8. 4
      shaders/shader.frag
  9. 49
      src/application.cpp
  10. 47
      src/vulkan/instance.cpp

4
.gitmodules vendored

@ -0,0 +1,4 @@
[submodule "lib/imgui"]
path = lib/imgui
url = https://github.com/ocornut/imgui.git
branch = docking

@ -1,10 +1,15 @@
cmake_minimum_required(VERSION 3.22)
project(VulkanSimulation)
include(CMakePrintHelpers)
set(CMAKE_CXX_STANDARD 20)
file(GLOB_RECURSE SRC_FILES src/**.cpp)
add_executable(VulkanSimulation ${SRC_FILES})
file(GLOB IMGUI_FILES lib/imgui/*.cpp lib/imgui/*.h lib/imgui/backends/imgui_impl_glfw* lib/imgui/backends/imgui_impl_vulkan*)
cmake_print_variables(IMGUI_FILES)
add_executable(VulkanSimulation ${SRC_FILES} ${IMGUI_FILES})
find_package(Vulkan REQUIRED)
find_package(OpenMP REQUIRED)
@ -21,6 +26,7 @@ target_compile_options(assimp PRIVATE -Wno-unknown-pragmas)
target_link_libraries(VulkanSimulation glm glfw Vulkan::Vulkan GPUOpen::VulkanMemoryAllocator assimp tet OpenMP::OpenMP_CXX)
target_include_directories(VulkanSimulation PRIVATE include lib)
target_include_directories(VulkanSimulation PRIVATE include lib/imgui)
target_compile_definitions(VulkanSimulation PRIVATE
GLM_FORCE_RADIANS
GLM_FORCE_DEPTH_ZERO_TO_ONE

@ -0,0 +1,27 @@
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Window][Dear ImGui Demo]
Pos=1568,0
Size=351,1004
Collapsed=0
[Window][Dear ImGui Metrics/Debugger]
Pos=91,122
Size=775,375
Collapsed=0
[Window][Dear ImGui Debug Log]
Pos=428,238
Size=380,328
Collapsed=0
[Window][Dear ImGui Style Editor]
Pos=153,27
Size=353,999
Collapsed=0
[Docking][Data]

@ -42,6 +42,7 @@ public:
void mainLoop();
~Application();
private:
void initIMGUI();
void createSyncObjects();
unique_ptr<Semaphore> imageAvailable;

@ -22,8 +22,8 @@ public:
void bindImage(const Image& image, VkDescriptorType type, DescriptorSet set, uint32_t binding);
std::map<DescriptorSet, VkDescriptorSet> sets;
std::map<DescriptorSet, VkDescriptorSetLayout> layouts;
private:
VkDescriptorPool handle = VK_NULL_HANDLE;
private:
void createLayout(DescriptorSet set, const std::vector<VkDescriptorSetLayoutBinding> &bindings);
};

@ -7,10 +7,14 @@
#include <set>
#include <vector>
#include "vk_mem_alloc.h"
#include "imgui.h"
#include "imgui/backends/imgui_impl_vulkan.h"
#include "imgui/backends/imgui_impl_glfw.h"
using std::optional, std::vector;
class CommandPool;
class Swapchain;
void printVmaStats();
@ -57,12 +61,15 @@ public:
static VkPhysicalDevice GetPhysicalDevice();
static VmaAllocator GetAllocator();
static VkSurfaceKHR GetSurface();
void initImGui(const Swapchain& swapchain);
private:
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
VkDevice device = VK_NULL_HANDLE;
VkSurfaceKHR surface = VK_NULL_HANDLE;
VmaAllocator allocator = VK_NULL_HANDLE;
VkDescriptorPool imGuiDescriptorPool = VK_NULL_HANDLE;
VkInstance handle = VK_NULL_HANDLE;
void initWindow();

@ -0,0 +1 @@
Subproject commit 4e2126ee44c066c642d89d25320fd32e449e5a9a

@ -10,7 +10,7 @@ layout (set = 0, binding = 2) uniform sampler2D texSampler;
void main() {
// outColor = vec4((normal + vec3(1, 1, 1)) / 2, 1.0);
vec3 L = vec3(1, 1, 1);
vec3 L = vec3(1, 5, 1);
L = normalize(L);
vec3 N = normal;
@ -21,7 +21,7 @@ void main() {
float lambertian = max(dot(L, N), 0);
vec3 diffuse = lambertian * albedo;
vec3 ambient = vec3(1, 1, 1) * 0.01;
vec3 ambient = albedo * 0.1;
vec3 C = ambient + diffuse;

@ -15,6 +15,14 @@
#include "timer.hpp"
#include "grabber.hpp"
#include "stb_image.h"
#include <future>
#include <chrono>
#include "imgui.h"
#include "imgui/backends/imgui_impl_vulkan.h"
#include "imgui/backends/imgui_impl_glfw.h"
using namespace std::chrono;
struct SizesUniformData {
uint32_t vertexCount;
@ -51,6 +59,7 @@ struct PBDPushData {
Application::Application() {
createSyncObjects();
swapchain = make_unique<Swapchain>();
Instance::instance->initImGui(*swapchain);
descriptorPool = make_unique<DescriptorPool>();
graphicsPipeline = unique_ptr<GraphicsPipeline>(new GraphicsPipeline("shaders/vert.spv", "shaders/frag.spv",
swapchain->renderPass,
@ -129,14 +138,11 @@ Application::Application() {
printVmaStats();
}
#include <future>
#include <chrono>
using namespace std::chrono;
void Application::mainLoop() {
vkDeviceWaitIdle(Instance::GetDevice());
std::future compute = std::async(std::launch::async, [this](){
setbuf(stdout, NULL);
descriptorPool->bindBuffer(*vertexBuffers[1 - currentDrawVertexBuffer], VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::MESH, 0);
while (!glfwWindowShouldClose(Instance::instance->window)){
auto t1 = system_clock::now();
update();
@ -145,12 +151,26 @@ void Application::mainLoop() {
auto measuredUpdateDuration = duration<float>(t2 - t1);
auto requestedUpdateDuration = duration<float>(simulationPropertiesBuffer->access<SimulationUniformData>().dt);
std::this_thread::sleep_for(requestedUpdateDuration - measuredUpdateDuration);
auto totalUpdateDuration = std::max(requestedUpdateDuration, measuredUpdateDuration);
printf("\r%f", totalUpdateDuration.count());
}
});
bool show_demo_window = true;
auto t1 = system_clock::now();
while (!glfwWindowShouldClose(Instance::instance->window)){
glfwPollEvents();
ImGui_ImplVulkan_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
ImGui::ShowDemoWindow(&show_demo_window);
ImGui::Render();
auto t2 = system_clock::now();
float seconds = duration<float>(t2 - t1).count();
t1 = system_clock::now();
@ -176,18 +196,18 @@ void Application::createSyncObjects() {
void Application::createMeshBuffers() {
Mesh sphere("models/icosphere.ply");
Mesh bunny("models/bunny_high.ply");
Mesh bunny("models/bunny_medium.ply");
auto body = std::make_unique<SoftBody>(&sphere, 1.f / 100);
auto body = std::make_unique<SoftBody>(&sphere, 1.f / 60);
for (size_t i = 0; i < 0; i++){
for (size_t i = 0; i < 5; i++){
auto copy = std::make_unique<SoftBody>(*body.get());
copy->applyVertexOffset({i * 2, 0, 0});
softBodies.push_back(std::move(copy));
}
body = std::make_unique<SoftBody>(&bunny, 1.f / 10);
for (size_t i = 0; i < 2; i++){
for (size_t i = 0; i < 5; i++){
auto copy = std::make_unique<SoftBody>(*body.get());
copy->applyVertexOffset({i * 2, 0, 2});
softBodies.push_back(std::move(copy));
@ -423,6 +443,8 @@ void Application::drawFrame(float dt) {
recordDrawCommands(cmdBuffer);
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmdBuffer);
vkCmdEndRenderPass(cmdBuffer);
vkEndCommandBuffer(cmdBuffer);
}
@ -485,11 +507,12 @@ void Application::update() {
vkResetFences(Instance::GetDevice(), 1, &computeFence->handle);
currentDrawVertexBuffer = 1 - currentDrawVertexBuffer;
descriptorPool->bindBuffer(*vertexBuffers[1 - currentDrawVertexBuffer], VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, DescriptorSet::MESH, 0);
vkWaitForFences(Instance::GetDevice(), 1, &transferFence->handle, VK_TRUE, UINT64_MAX);
vkResetFences(Instance::GetDevice(), 1, &transferFence->handle);
currentDrawVertexBuffer = 1 - currentDrawVertexBuffer;
VkCommandBufferBeginInfo beginInfo {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = 0;
@ -687,9 +710,3 @@ void Application::recordNormalCommands(VkCommandBuffer cmdBuffer) {
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, &barrier, 0, nullptr, 0, nullptr);
}

@ -70,6 +70,7 @@ void Instance::initWindow() {
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE);
window = glfwCreateWindow(800, 600, "Vulkan Simulation", nullptr, nullptr);
glfwSetFramebufferSizeCallback(window, [](GLFWwindow* window, int width, int height) {
instance->windowResized = true;
@ -283,6 +284,12 @@ VkSurfaceKHR Instance::GetSurface() {
Instance::~Instance() {
delete renderingCommandPool;
delete computeCommandPool;
ImGui_ImplVulkan_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
vkDestroyDescriptorPool(Instance::GetDevice(), imGuiDescriptorPool, nullptr);
vmaDestroyAllocator(allocator);
vkDestroyDevice(device, nullptr);
vkDestroySurfaceKHR(handle, surface, nullptr);
@ -291,3 +298,43 @@ Instance::~Instance() {
glfwDestroyWindow(window);
glfwTerminate();
}
void Instance::initImGui(const Swapchain& swapchain) {
ImGui::CreateContext();
ImGui::StyleColorsDark();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
ImGui_ImplGlfw_InitForVulkan(window, true);
VkDescriptorPoolSize pool_sizes[] = {
{
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1
}
};
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 = 1;
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
pool_info.pPoolSizes = pool_sizes;
vkCreateDescriptorPool(Instance::GetDevice(), &pool_info, nullptr, &imGuiDescriptorPool);
ImGui_ImplVulkan_InitInfo initInfo {};
initInfo.Instance = handle;
initInfo.PhysicalDevice = physicalDevice;
initInfo.Device = device;
initInfo.QueueFamily = renderingCommandPool->queueFamilyIndex;
initInfo.Queue = graphicsAndPresentQueue;
initInfo.PipelineCache = VK_NULL_HANDLE;
initInfo.DescriptorPool = imGuiDescriptorPool;
initInfo.RenderPass = swapchain.renderPass;
initInfo.Subpass = 0;
initInfo.MinImageCount = swapchain.frameBuffers.size();
initInfo.ImageCount = swapchain.frameBuffers.size();
initInfo.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
initInfo.Allocator = VK_NULL_HANDLE;
initInfo.CheckVkResultFn = VK_NULL_HANDLE;
ImGui_ImplVulkan_Init(&initInfo);
}

Loading…
Cancel
Save