Added Draft on starting a vulkan ImGui context

Timothy Gibbons 2021-07-28 10:59:31 -05:00
parent 3c24fcb799
commit e137cee46d

143
Integrating-with-Vulkan.md Normal file

@ -0,0 +1,143 @@
# Introduction
Vulkan is a modern low level graphics api. With vulkan there are changes that is different from OpenGL and DirectX.
This wiki page is inspired by the article from (François Guthmann)[https://frguthmann.github.io/posts/vulkan_imgui/]
This is no way a Vulkan tutorial. To get an idea of the Vulkan API please follow the (vulkan-tutorial)[https://vulkan-tutorial.com/]
Note: I am using Vulkan-HPP headers, but you can certainly use the vulkan.h headers.
# Implementation
## ImGui Header Files
* `imconfig.h`
* `imgui.h`
* `imgui_internal.h`
* `imstb_rectpack.h`
* `imstb_textedit.h`
* `imstb_truetype.h`
## ImGui Source Files
The ImGUI source files you're going to need is.
* `imgui.cpp`
* `imgui_demo.cpp` (optional)
* `imgui_draw.cpp`
* `imgui_tables.cpp`
* `imgui_widgets.cpp`
## Vulkan Components that is needed for ImGui
- `VkInstance`
- `VkPhysicalDevice`
- `VkDevice`
- `VkQueueFamily`
- `VkQueue`
- `VkDescriptorPool`
- `VkCommandPool`
- `VkCommandBuffer`
- `VkRenderPass`
- `VkFramebuffer`
## Initialize
First we need to initialize Vulkan. You should already have done so if you're following the (vulkan-tutorial)[https://vulkan-tutorial.com/]. After getting Vulkan running, we can start an ImGui context. It's recommended to create a seperate `VkDescriptorPool`, `VkRenderPass`, `VkCommandBuffer`, and `VkFramebuffer`.
```c++
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
ImGui_Impl{platform}_InitForVulkan(window, true);
```
After starting an ImGui context, we give ImGui some of the application Vulkan bindings through an `ImGui_ImplVulkan_InitInfo` struct. We then call `ImGui_ImplVulkan_Init()` passing in a pointer to the `ImGui_ImplVulkan_InitInfo` and a `VkRenderPass`. This will initalize Vulkan for ImGui.
We then upload font textures to the GPU.
```c++
// Allocate a command buffer
// Record our command buffer
cb.begin({vk::CommandBufferUsageFlagBits::eOneTimeSubmit});
ImGui_ImplVulkan_CreateFontsTexture(cb);
cb.end();
// Submit to the GPU
vk::SubmitInfo si;
si.commandBufferCount = cb.size();
si.pCommandBuffers = cb.data();
vk::Result res = device->getGraphicsQueue().submit(1, &si, {});
device->getGraphicsQueue().waitIdle(); // Wait for cb is complete
```
### Begin Frame
We need to call the following every frame.
```c++
ImGui_ImplVulkan_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
```
### Ending Frame
When we end the frame, we want to build the model so we can render this to the screen.
```c++
ImGuiIO& io = ::ImGui::GetIO();
ImGui::Render();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable){
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
}
```
### Render
Once we have the model we can finally submit the draw call.
```c++
vk::ClearValue clearValue;
clearValue.color = vk::ClearColorValue(std::array<float, 4>({0.0f, 0.0f, 0.0f, 1.0f}));
cb.begin({vk::CommandBufferUsageFlags()});
cb.beginRenderPass({
imguiRenderPass,
imguiFramebuffers[swapchainCurrentImage],
{{0,0}, swapchainExtent},
1, &clearValue
}, vk::SubpassContents::eInline);
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cb);
cb.endRenderPass();
cb.end();
vk::SubmitInfo si;
si.commandBufferCount = 1;
si.pCommandBuffers = &cb;
graphicsQueue->submit(si);
```
### Resize
When the window viewport resizes, we must create a new `VkFramebuffer` and `VkRenderPass`
### Clean up
At the end of the application life-cycle, we must destroy our ImGui context.
* `ImGui_ImplVulkan_Shutdown()`
* `ImGui_ImplGlfw_Shutdown()`
* `ImGui::DestroyContext()`
## Using the API
In our application life cycle we should have
```c++
while(true){
updateWindow();
rendererBeginFrame(); // Acquire images
imguiBeginFrame();
ImGui::ShowDemoWindow(); // Issue ImGui commands
imguiEndFrame();
imguiRender(); // Submit Command buffers to screen
rendererPresent(); // Present to the screen
}
```