xo-imgui wip

This commit is contained in:
Roland Conybeare 2025-09-24 23:24:35 -04:00
commit 7497751192
4 changed files with 233 additions and 26 deletions

View file

@ -23,6 +23,17 @@ VulkanApp::VulkanApp(ImguiDrawFn draw_fn)
{
}
float
VulkanApp::lifetime_fps() const {
if (n_frame_ > 0) {
float elapsed_sec = 1.0e-3f * std::chrono::duration_cast<std::chrono::milliseconds>(now_tm_ - start_tm_).count();
return n_frame_ / elapsed_sec;
} else {
return 0.0;
}
}
void
VulkanApp::setup(std::function<void (ImGuiContext *)> load_fonts) {
if (!setup_done_) {
@ -55,7 +66,8 @@ VulkanApp::init_window() {
this->window_ = SDL_CreateWindow("Xo ImGui Vulkan SDL2 Frame",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
800, 600,
600, 600,
//1250, 1200,
SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE);
if (!window_) {
@ -83,6 +95,8 @@ VulkanApp::init_vulkan()
void
VulkanApp::create_instance()
{
scope log(XO_DEBUG(true));
VkApplicationInfo appInfo{};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "ImGui Vulkan App";
@ -128,6 +142,11 @@ VulkanApp::create_instance()
// CRITICAL: Enable portability enumeration flag for MoltenVK
createInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
log && log(xtag("vkCreateInstance.layers", createInfo.enabledLayerCount));
for (uint32_t i = 0; i < createInfo.enabledLayerCount; ++i) {
log && log(xtag("i", i), xtag("layer[i]", createInfo.ppEnabledLayerNames[i]));
}
if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
throw std::runtime_error("Failed to create instance!");
}
@ -205,9 +224,27 @@ VulkanApp::create_logical_device()
vkGetDeviceQueue(device_, graphics_queue_family_, 0, &graphics_queue_);
}
const char *
present_mode_descr(VkPresentModeKHR m) {
switch(m) {
case VK_PRESENT_MODE_IMMEDIATE_KHR: return "immediate";
case VK_PRESENT_MODE_MAILBOX_KHR: return "mailbox";
case VK_PRESENT_MODE_FIFO_KHR: return "fifo";
case VK_PRESENT_MODE_FIFO_RELAXED_KHR: return "fifo-relaxed";
case VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR: return "shared-demand-refresh";
case VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR: return "shared-continuous-refresh";
case VK_PRESENT_MODE_FIFO_LATEST_READY_EXT: return "fifo-latest-ready";
case VK_PRESENT_MODE_MAX_ENUM_KHR: break;
}
return "?present-mode";
}
void
VulkanApp::create_swapchain()
{
scope log(XO_DEBUG(true));
VkSurfaceCapabilitiesKHR capabilities;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR
(physical_device_, surface_, &capabilities);
@ -234,6 +271,40 @@ VulkanApp::create_swapchain()
imageCount = capabilities.maxImageCount;
}
VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
{
uint32_t n_avail_mode = 0;
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device_, surface_, &n_avail_mode, nullptr);
std::vector<VkPresentModeKHR> avail_mode_v(n_avail_mode);
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device_, surface_, &n_avail_mode, avail_mode_v.data());
if (log) {
log(xtag("n_avail_present_mode", n_avail_mode));
for (uint32_t i = 0; i < n_avail_mode; ++i)
log(xtag("i", i), xtag("avail_mode_v[i]", present_mode_descr(avail_mode_v[i])));
}
std::vector<VkPresentModeKHR> prefer_mode_v = {
VK_PRESENT_MODE_IMMEDIATE_KHR,
VK_PRESENT_MODE_MAILBOX_KHR,
VK_PRESENT_MODE_FIFO_KHR // forces vsync, v.slow on wsl
};
bool found_flag = false;
for (uint32_t i = 0; i < prefer_mode_v.size() && !found_flag; ++i) {
for (uint32_t j = 0; j < avail_mode_v.size() && !found_flag; ++j) {
if (prefer_mode_v[i] == avail_mode_v[j]) {
present_mode = prefer_mode_v[i];
found_flag = true;
}
}
}
log && log(xtag("present_mode", present_mode_descr(present_mode)));
}
VkSwapchainCreateInfoKHR createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
createInfo.surface = surface_;
@ -246,7 +317,7 @@ VulkanApp::create_swapchain()
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
createInfo.preTransform = capabilities.currentTransform;
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
createInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR;
createInfo.presentMode = present_mode;
createInfo.clipped = VK_TRUE;
if (vkCreateSwapchainKHR
@ -710,15 +781,18 @@ VulkanApp::draw_frame()
} /*draw_frame*/
void
VulkanApp::record_command_buffer(VkCommandBuffer commandBuffer,
VulkanApp::record_command_buffer(VkCommandBuffer command_buffer,
uint32_t imageIndex)
{
// as long as we do this per-frame, independent of swapchain
if (n_frame_ == 0) {
this->start_tm_ = std::chrono::steady_clock::now();
}
VkCommandBufferBeginInfo begin_info{};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
if (vkBeginCommandBuffer(commandBuffer, &begin_info) != VK_SUCCESS) {
if (vkBeginCommandBuffer(command_buffer, &begin_info) != VK_SUCCESS) {
throw std::runtime_error("Failed to begin recording command buffer!");
}
@ -733,17 +807,34 @@ VulkanApp::record_command_buffer(VkCommandBuffer commandBuffer,
render_pass_info.clearValueCount = 1;
render_pass_info.pClearValues = &clear_color;
vkCmdBeginRenderPass(commandBuffer,
vkCmdBeginRenderPass(command_buffer,
&render_pass_info,
VK_SUBPASS_CONTENTS_INLINE);
ImDrawData * draw_data = this->imgui_draw_frame_(imgui_cx_);
ImDrawData * draw_data = this->imgui_draw_frame_(imgui_cx_); (void)draw_data;
ImGui_ImplVulkan_RenderDrawData(draw_data, commandBuffer);
#ifdef TEMPORARILY_REMOVE
ImGui_ImplVulkan_RenderDrawData(draw_data, command_buffer);
#endif
vkCmdEndRenderPass(commandBuffer);
vkCmdEndRenderPass(command_buffer);
if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
{
++(this->n_frame_);
this->now_tm_ = std::chrono::steady_clock::now();
if ((this->n_frame_ == 1)
|| (std::chrono::duration_cast<std::chrono::seconds>(now_tm_ - last_log_fps_tm_).count() > 1))
{
this->last_log_fps_tm_ = now_tm_;
scope log(XO_DEBUG(true));
log && log(xtag("lifetime_fps", this->lifetime_fps()));
}
}
if (vkEndCommandBuffer(command_buffer) != VK_SUCCESS) {
throw std::runtime_error("Failed to record command buffer!");
}
}