xo-imgui: imgui_ex4 working on native ubuntu
requires etc/hostubuntu shim
This commit is contained in:
parent
826298d097
commit
5fcfadce9a
5 changed files with 555 additions and 586 deletions
|
|
@ -1,9 +1,6 @@
|
|||
/* imgui_ex4.cpp */
|
||||
|
||||
#include "xo/imgui/VulkanApp.hpp"
|
||||
#ifdef TEMPORARILY_REMOVE
|
||||
#include "xo/imgui/ImRect.hpp"
|
||||
#endif
|
||||
#include "AppState.hpp"
|
||||
#include "DrawState.hpp"
|
||||
#include <backends/imgui_impl_sdl2.h>
|
||||
|
|
@ -87,9 +84,7 @@ namespace {
|
|||
{
|
||||
scope log(XO_DEBUG(false));
|
||||
|
||||
#ifdef TEMPORARILY_REMOVE
|
||||
app_duty_cycle_top(p_app_state, p_draw_state);
|
||||
#endif
|
||||
|
||||
log && log(xtag("imgui_cx", (void*)ImGui::GetCurrentContext()));
|
||||
|
||||
|
|
@ -98,7 +93,6 @@ namespace {
|
|||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
#ifdef TEMPORARILY_REMOVE
|
||||
log && log("after NewFrame", xtag("imgui_cx", (void*)ImGui::GetCurrentContext()));
|
||||
|
||||
ImGuiIO & io = ImGui::GetIO(); (void)io;
|
||||
|
|
@ -113,12 +107,10 @@ namespace {
|
|||
| ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoDecoration);
|
||||
ImGui::End();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// 1. create a simple ImGui window
|
||||
ImGui::Begin("Hello, Vulkan + SDL2!");
|
||||
ImGui::Text("This is a minimal ImGui + Vulkan + SDL2 example!");
|
||||
#ifdef TEMPORARILY_REMOVE
|
||||
ImGui::Text("appl average %.3f ms/frame (%.1f fps)",
|
||||
1000.0f / io.Framerate, io.Framerate);
|
||||
|
||||
|
|
@ -212,15 +204,12 @@ namespace {
|
|||
p_app_state->copy_detail_tenured_dest_size_ = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ImGui::End();
|
||||
|
||||
#ifdef TEMPORARILY_REMOVE
|
||||
// 2. big demo window
|
||||
if (p_draw_state->show_demo_window_)
|
||||
ImGui::ShowDemoWindow(&p_draw_state->show_demo_window_);
|
||||
#endif
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
|
|
@ -296,13 +285,10 @@ int main() {
|
|||
= make_imgui_draw_frame(&app_state, &draw_state, &f, &counter);
|
||||
VulkanApp vk_app(draw_fn);
|
||||
|
||||
/* establishes imgui context */
|
||||
vk_app.setup(app_imgui_load_fonts);
|
||||
|
||||
#ifdef NOT_YET
|
||||
app_state.gc_->add_gc_copy_callback
|
||||
(draw_state.make_gc_copy_animation(&app_state));
|
||||
#endif
|
||||
|
||||
try {
|
||||
vk_app.main_loop();
|
||||
|
|
|
|||
|
|
@ -41,10 +41,7 @@ MinimalImGuiVulkan::init_vulkan()
|
|||
this->create_surface();
|
||||
this->pick_physical_device();
|
||||
this->create_logical_device();
|
||||
this->create_swapchain();
|
||||
this->create_image_views();
|
||||
this->create_render_pass(); // must come before createFrameBuffers
|
||||
this->create_framebuffers();
|
||||
this->create_xswapchain(true /*create_render_pass_flag*/);
|
||||
this->create_command_pool();
|
||||
this->create_command_buffers();
|
||||
this->create_sync_objects();
|
||||
|
|
@ -503,7 +500,7 @@ MinimalImGuiVulkan::draw_frame()
|
|||
case VK_SUBOPTIMAL_KHR:
|
||||
break;
|
||||
case VK_ERROR_OUT_OF_DATE_KHR:
|
||||
recreate_swapchain();
|
||||
this->recreate_xswapchain();
|
||||
// deliberate earlyexit
|
||||
return;
|
||||
default:
|
||||
|
|
@ -559,7 +556,7 @@ MinimalImGuiVulkan::draw_frame()
|
|||
case VK_ERROR_OUT_OF_DATE_KHR:
|
||||
case VK_SUBOPTIMAL_KHR:
|
||||
framebuffer_resized_flag_ = false;
|
||||
this->recreate_swapchain();
|
||||
this->recreate_xswapchain();
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("failed to present swapchain image!");
|
||||
|
|
@ -624,7 +621,25 @@ MinimalImGuiVulkan::record_command_buffer(VkCommandBuffer cmdbuf, uint32_t image
|
|||
}
|
||||
|
||||
void
|
||||
MinimalImGuiVulkan::recreate_swapchain()
|
||||
MinimalImGuiVulkan::create_xswapchain(bool create_render_pass_flag)
|
||||
{
|
||||
this->create_swapchain();
|
||||
this->create_image_views();
|
||||
if(create_render_pass_flag)
|
||||
this->create_render_pass();
|
||||
this->create_framebuffers();
|
||||
}
|
||||
|
||||
void
|
||||
MinimalImGuiVulkan::cleanup_xswapchain()
|
||||
{
|
||||
this->cleanup_framebuffers();
|
||||
this->cleanup_image_views();
|
||||
this->cleanup_swapchain();
|
||||
}
|
||||
|
||||
void
|
||||
MinimalImGuiVulkan::recreate_xswapchain()
|
||||
{
|
||||
// handle window minimization: wait until window has valid size
|
||||
this->wait_not_minimized();
|
||||
|
|
@ -632,15 +647,11 @@ MinimalImGuiVulkan::recreate_swapchain()
|
|||
// wait until device idle before cleaning up resources
|
||||
vkDeviceWaitIdle(device_);
|
||||
|
||||
// cleanup old swapchain
|
||||
this->cleanup_framebuffers();
|
||||
this->cleanup_image_views();
|
||||
this->cleanup_swapchain();
|
||||
// cleanup old xswapchain
|
||||
this->cleanup_xswapchain();
|
||||
|
||||
// create new swapchain
|
||||
this->create_swapchain();
|
||||
this->create_image_views();
|
||||
this->create_framebuffers();
|
||||
this->create_xswapchain(false);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -694,9 +705,7 @@ MinimalImGuiVulkan::cleanup()
|
|||
|
||||
vkDestroyCommandPool(device_, command_pool_, nullptr);
|
||||
|
||||
this->cleanup_framebuffers();
|
||||
this->cleanup_image_views();
|
||||
this->cleanup_swapchain();
|
||||
this->cleanup_xswapchain();
|
||||
|
||||
vkDestroyRenderPass(device_, render_pass_, nullptr);
|
||||
vkDestroyDescriptorPool(device_, descriptor_pool_, nullptr);
|
||||
|
|
|
|||
|
|
@ -47,6 +47,12 @@ private:
|
|||
*/
|
||||
void create_logical_device();
|
||||
|
||||
/* populates @ref swapchain_, @ref swapchain_images_,
|
||||
* @ref swapchain_image_views_, @ref framebuffers_.
|
||||
* Also $ref render_pass_ iff @p create_render_pass_flag
|
||||
*/
|
||||
void create_xswapchain(bool create_render_pass_flag);
|
||||
|
||||
/*
|
||||
* populates @ref swapchain_, @ref swapchain_images_
|
||||
*/
|
||||
|
|
@ -123,11 +129,14 @@ private:
|
|||
/* Teardown + create swapchain (swapchain + framebuffers + image views).
|
||||
* Need this after window size changes
|
||||
*/
|
||||
void recreate_swapchain();
|
||||
void recreate_xswapchain();
|
||||
|
||||
/* wait until non-minimized window */
|
||||
void wait_not_minimized();
|
||||
|
||||
/* orderly disposal of swapchin + image_views + framebuffers */
|
||||
void cleanup_xswapchain();
|
||||
|
||||
/* orderly disposal of @ref framebuffers_ */
|
||||
void cleanup_framebuffers();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,115 +1,221 @@
|
|||
/* file VulkanApp.hpp */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <SDL.h>
|
||||
#include <imgui.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
//#include <SDL_vulkan.h>
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <SDL.h>
|
||||
#include <SDL_vulkan.h>
|
||||
#include <imgui.h>
|
||||
#include <backends/imgui_impl_sdl2.h>
|
||||
#include <backends/imgui_impl_vulkan.h>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
class VulkanApp {
|
||||
public:
|
||||
using ImguiDrawFn = std::function<ImDrawData * (ImGuiContext *)>;
|
||||
using time_point = std::chrono::steady_clock::time_point;
|
||||
|
||||
public:
|
||||
/* create single-window vulkan application;
|
||||
* use @p fn to draw each frame
|
||||
*/
|
||||
VulkanApp(ImguiDrawFn fn);
|
||||
|
||||
#ifdef NOPE
|
||||
/** set imgui draw function **/
|
||||
void assign_imgui_draw_frame(ImguiDrawFn fn);
|
||||
#endif
|
||||
/* run application; borrows calling thread for event loop,
|
||||
* until application exit.
|
||||
* Invoke load_fonts once imgui context established
|
||||
*/
|
||||
void run(std::function<void (ImGuiContext *)> load_fonts);
|
||||
|
||||
/** frames per second since inception **/
|
||||
float lifetime_fps() const;
|
||||
|
||||
/** equivalent to sequence setup(), main_loop(), cleanup() **/
|
||||
void run();
|
||||
|
||||
/** setup before main loop. idempotent **/
|
||||
/* application setup (sdl -> vulkan -> imgui)
|
||||
* Invoke load_fonts once imgui context established.
|
||||
*/
|
||||
void setup(std::function<void (ImGuiContext *)> load_fonts);
|
||||
|
||||
/* borrow calling thread, run until application end
|
||||
* Require: app state initialized. see init_sdl_window(), init_vulkan(), init_imgui()
|
||||
*/
|
||||
void main_loop();
|
||||
/** cleanup before shutdown. idempotent **/
|
||||
|
||||
/* orderly shutdown
|
||||
*/
|
||||
void cleanup();
|
||||
|
||||
private:
|
||||
void init_window();
|
||||
/* create SDL window for application.
|
||||
* populates @ref window_
|
||||
*/
|
||||
void init_sdl_window();
|
||||
|
||||
/* setup vulkan state. swapchain, command buffers etc */
|
||||
void init_vulkan();
|
||||
|
||||
/* create vulkan instance.
|
||||
* populates @ref instance_
|
||||
*/
|
||||
void create_instance();
|
||||
|
||||
/* create vulkan surface.
|
||||
* populates @ref surface_
|
||||
*/
|
||||
void create_surface();
|
||||
|
||||
/* choose physical device (1:1 with graphics card, presumably)
|
||||
* populates @ref physical_device_, @ref graphics_queue_family_
|
||||
*/
|
||||
void pick_physical_device();
|
||||
|
||||
/*
|
||||
* require: pick_physical_device() has run successfully
|
||||
* populates @ref device_, @ref graphics_queue_
|
||||
*/
|
||||
void create_logical_device();
|
||||
|
||||
/* populates @ref swapchain_, @ref swapchain_images_,
|
||||
* @ref swapchain_image_views_, @ref framebuffers_.
|
||||
* Also $ref render_pass_ iff @p create_render_pass_flag
|
||||
*/
|
||||
void create_xswapchain(bool create_render_pass_flag);
|
||||
|
||||
/*
|
||||
* populates @ref swapchain_, @ref swapchain_images_
|
||||
*/
|
||||
void create_swapchain();
|
||||
|
||||
/*
|
||||
* populate @ref swapchain_image_views_
|
||||
*/
|
||||
void create_image_views();
|
||||
|
||||
/*
|
||||
* populate @ref render_pass_
|
||||
*/
|
||||
void create_render_pass();
|
||||
|
||||
/*
|
||||
* populate @ref framebuffers_
|
||||
*/
|
||||
void create_framebuffers();
|
||||
|
||||
/*
|
||||
* populate @ref command_pool_
|
||||
*/
|
||||
void create_command_pool();
|
||||
|
||||
/*
|
||||
* populate @ref command_buffers_
|
||||
*/
|
||||
void create_command_buffers();
|
||||
|
||||
/*
|
||||
* populate
|
||||
* @ref image_available_semaphores_,
|
||||
* @ref render_finished_semaphores_,
|
||||
* @ref inflight_fences_
|
||||
*/
|
||||
void create_sync_objects();
|
||||
|
||||
/*
|
||||
* populate @ref descriptor_pool_
|
||||
*/
|
||||
void create_descriptor_pool();
|
||||
|
||||
void cleanup_framebuffers();
|
||||
void cleanup_render_pass();
|
||||
void cleanup_image_views();
|
||||
void cleanup_swapchain();
|
||||
|
||||
void cleanup_swapchain_deps();
|
||||
void recreate_swapchain_deps();
|
||||
|
||||
/* Setup imgui "framework".
|
||||
* Invoke @p load_fonts with ImGuiContext
|
||||
*/
|
||||
void init_imgui(std::function<void (ImGuiContext *)> load_fonts);
|
||||
|
||||
/* Allocate buffer for 'single-time' commands (to be run once?).
|
||||
* Pair with call to end_single_time_commands()
|
||||
*/
|
||||
VkCommandBuffer begin_single_time_commands();
|
||||
|
||||
/* complete command buffer begun with begin_single_time_commands();
|
||||
* also submit, wait for completion + cleanup
|
||||
*/
|
||||
void end_single_time_commands(VkCommandBuffer commandBuffer);
|
||||
void record_command_buffer(VkCommandBuffer commandBuffer,
|
||||
uint32_t imageIndex);
|
||||
/** TODO: replace with some generic mechanism **/
|
||||
|
||||
/* Accumulate drawing command for next frame.
|
||||
* Reserves and modifies the @ref current_frame_ element of
|
||||
* @ref command_buffers_
|
||||
* @ref image_available_semaphores_
|
||||
* @ref inflight_fences_
|
||||
* Advances current_frame_ so that it refers to available resources
|
||||
*/
|
||||
void draw_frame();
|
||||
|
||||
private:
|
||||
bool setup_done_ = false;
|
||||
bool cleanup_done_ = false;
|
||||
/* record draw instructions into cmdbuf, framebuffers_[image_ix] */
|
||||
void record_command_buffer(VkCommandBuffer commandBuffer, uint32_t image_ix);
|
||||
|
||||
/* Teardown + create swapchain (swapchain + framebuffers + image views).
|
||||
* Need this after window size changes
|
||||
*/
|
||||
void recreate_xswapchain();
|
||||
|
||||
/* wait until non-minimized window */
|
||||
void wait_not_minimized();
|
||||
|
||||
/* orderly disposal of swapchin + image_views + framebuffers */
|
||||
void cleanup_xswapchain();
|
||||
|
||||
/* orderly disposal of @ref framebuffers_ */
|
||||
void cleanup_framebuffers();
|
||||
|
||||
/* orderly disposal of @ref swapchain_image_views_ */
|
||||
void cleanup_image_views();
|
||||
|
||||
/* orderly disposal of @ref swapchain_ */
|
||||
void cleanup_swapchain();
|
||||
|
||||
private:
|
||||
SDL_Window* window_ = nullptr;
|
||||
ImGuiContext* imgui_cx_ = nullptr;
|
||||
VkInstance instance;
|
||||
|
||||
VkInstance instance_;
|
||||
|
||||
/* abstraction for presentation area (?) */
|
||||
VkSurfaceKHR surface_;
|
||||
|
||||
/* physical device (graphics card) */
|
||||
VkPhysicalDevice physical_device_;
|
||||
uint32_t graphics_queue_family_ = 0;
|
||||
|
||||
/* logical device (graphics card, abstract api (?)) */
|
||||
VkDevice device_;
|
||||
VkQueue graphics_queue_;
|
||||
VkSurfaceKHR surface_;
|
||||
VkSwapchainKHR swapchain_;
|
||||
|
||||
/* drawing state, dependent on window size */
|
||||
VkFormat swapchain_image_format_;
|
||||
VkExtent2D swapchain_extent_;
|
||||
std::vector<VkImage> swapchainImages;
|
||||
VkSwapchainKHR swapchain_;
|
||||
std::vector<VkImage> swapchain_images_;
|
||||
|
||||
std::vector<VkImageView> swapchain_image_views_;
|
||||
|
||||
VkRenderPass render_pass_;
|
||||
|
||||
std::vector<VkFramebuffer> framebuffers_;
|
||||
|
||||
VkCommandPool command_pool_;
|
||||
|
||||
std::vector<VkCommandBuffer> command_buffers_;
|
||||
/** one per frame (up to MAX_FRAMES_IN_FLIGHT) **/
|
||||
|
||||
std::vector<VkSemaphore> image_available_semaphores_;
|
||||
/** one per frame (up to MAX_FRAMES_IN_FLIGHT) **/
|
||||
std::vector<VkSemaphore> render_finished_semaphores_;
|
||||
std::vector<VkFence> in_flight_fences_;
|
||||
std::vector<VkFence> inflight_fences_;
|
||||
|
||||
VkDescriptorPool descriptor_pool_;
|
||||
|
||||
/** frame counter, monotonic **/
|
||||
uint32_t n_frame_ = 0;
|
||||
/** VulkanApp start time. Captured in 1st render loop, see @ref record_command_buffer **/
|
||||
time_point start_tm_;
|
||||
/** time asof most recent render loop **/
|
||||
time_point now_tm_;
|
||||
/** time of last console report of fps **/
|
||||
time_point last_log_fps_tm_;
|
||||
|
||||
/** image index of current frame **/
|
||||
uint32_t current_frame_ = 0;
|
||||
uint32_t graphics_queue_family_ = 0;
|
||||
bool quit_ = false;
|
||||
const size_t c_max_frames_in_flight = 2;
|
||||
/* true iff @ref setup has been called */
|
||||
bool setup_flag_ = false;
|
||||
/* true when window resize behavior detected,
|
||||
* until swapchain in consistent state.
|
||||
*/
|
||||
bool framebuffer_resized_flag_ = false;
|
||||
bool quit_flag_ = false;
|
||||
|
||||
/** draw imgui **/
|
||||
const ImguiDrawFn imgui_draw_frame_;
|
||||
};
|
||||
|
||||
/* end VulkanApp.hpp */
|
||||
}; /*VulkanApp*/
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue