diff options
| author | hachem <im@hachem.wtf> | 2026-08-20 16:51:57 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-08-20 16:51:57 +0200 |
| commit | ca9b8beaf69f06cac9b91b66ccd03bb99f09dd22 (patch) | |
| tree | d1c40b26920eb901ba980b146238399807823642 | |
| parent | 9a19ae463880e06bae84eb8ae1b7279595ecdc38 (diff) | |
[chore]: move imgui HDRI switching to vulkan
| -rw-r--r-- | src/core/application.cpp | 28 | ||||
| -rw-r--r-- | src/platform/vulkan/vulkan_renderer.cpp | 38 | ||||
| -rw-r--r-- | src/platform/vulkan/vulkan_renderer.h | 9 |
3 files changed, 70 insertions, 5 deletions
diff --git a/src/core/application.cpp b/src/core/application.cpp index 667fc73..701e088 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -2,6 +2,7 @@ #include "rendering/renderer.h" #include "settings_manager.h" +#include "hdri_manager.h" #include "states/simulation_state.h" #include "states/config_state.h" @@ -80,15 +81,32 @@ namespace Donut auto Application::build_vulkan_ui() -> void { - // Placeholder UI proving the ImGui Vulkan backend renders. The real - // application UI (states' on_im_ui_render) moves here once the scene is - // ported to Vulkan (B-3). ImGui::Begin("Donut - Vulkan backend"); ImGui::Text("Geodesic black hole through Vulkan (MoltenVK)."); ImGui::Text("%.1f FPS", ImGui::GetIO().Framerate); ImGui::Separator(); - ImGui::TextWrapped("Drag to orbit, scroll to zoom. HDRI starfield is live; " - "next is porting the simulation UI to Vulkan."); + + if (m_vulkan_renderer) + { + auto& hdri = HDRIManager::get(); + std::string current = m_vulkan_renderer->current_hdri(); + std::string preview = hdri.get_hdri_name(current); + if (ImGui::BeginCombo("HDRI", preview.c_str())) + { + for (const auto& path : hdri.get_available_hdri()) + { + bool selected = (path == current); + if (ImGui::Selectable(hdri.get_hdri_name(path).c_str(), selected)) + m_vulkan_renderer->set_hdri(path); + if (selected) ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + ImGui::TextDisabled("Switching rebuilds the cubemap (brief pause)."); + } + + ImGui::Separator(); + ImGui::TextWrapped("Drag to orbit, scroll to zoom."); ImGui::End(); } diff --git a/src/platform/vulkan/vulkan_renderer.cpp b/src/platform/vulkan/vulkan_renderer.cpp index 95a546b..104bb62 100644 --- a/src/platform/vulkan/vulkan_renderer.cpp +++ b/src/platform/vulkan/vulkan_renderer.cpp @@ -99,6 +99,7 @@ namespace Donut bool left_was_down = false; VkImage cube_image = VK_NULL_HANDLE; VkDeviceMemory cube_mem = VK_NULL_HANDLE; VkImageView cube_view = VK_NULL_HANDLE; VkSampler cube_sampler = VK_NULL_HANDLE; + std::string hdri_path; // path backing the current cubemap (UI display + no-op switch guard) VkDescriptorSetLayout geo_set_layout = VK_NULL_HANDLE; VkDescriptorPool geo_pool = VK_NULL_HANDLE; VkDescriptorSet geo_set = VK_NULL_HANDLE; @@ -132,6 +133,7 @@ namespace Donut auto create_sync_objects() -> bool; auto create_geodesic_resources() -> bool; auto create_hdri_cubemap(const char* path) -> bool; + auto rebuild_hdri_cubemap(const char* path) -> void; auto create_present_resources() -> bool; auto process_input() -> void; auto update_geodesic_uniforms() -> void; @@ -601,6 +603,7 @@ namespace Donut auto VulkanRenderer::Impl::create_hdri_cubemap(const char* path) -> bool { + hdri_path = path; const VkMemoryPropertyFlags host_vis = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; const uint32_t FACE = 1024; const VkFormat cube_fmt = VK_FORMAT_R16G16B16A16_SFLOAT; @@ -845,6 +848,28 @@ namespace Donut return true; } + // Runtime HDRI switch: drain the device, tear down the old cubemap, build the + // new one, and repoint the geodesic set's samplerCube (binding 4) at it. + auto VulkanRenderer::Impl::rebuild_hdri_cubemap(const char* path) -> void + { + vkDeviceWaitIdle(device); + + if (cube_sampler) vkDestroySampler(device, cube_sampler, nullptr); + if (cube_view) vkDestroyImageView(device, cube_view, nullptr); + if (cube_image) vkDestroyImage(device, cube_image, nullptr); + if (cube_mem) vkFreeMemory(device, cube_mem, nullptr); + cube_sampler = VK_NULL_HANDLE; cube_view = VK_NULL_HANDLE; + cube_image = VK_NULL_HANDLE; cube_mem = VK_NULL_HANDLE; + + create_hdri_cubemap(path); + + VkDescriptorImageInfo cube_info{ cube_sampler, cube_view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }; + VkWriteDescriptorSet write{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET }; + write.dstSet = geo_set; write.dstBinding = 4; write.descriptorCount = 1; + write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; write.pImageInfo = &cube_info; + vkUpdateDescriptorSets(device, 1, &write, 0, nullptr); + } + auto VulkanRenderer::Impl::create_present_resources() -> bool { VkSamplerCreateInfo smci{ VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO }; @@ -1138,6 +1163,19 @@ namespace Donut m_impl->width = width; m_impl->height = height; } + auto VulkanRenderer::set_hdri(const std::string& path) -> void + { + Impl& v = *m_impl; + if (v.device == VK_NULL_HANDLE || v.geo_set == VK_NULL_HANDLE) return; + if (v.hdri_path == path) return; + v.rebuild_hdri_cubemap(path.c_str()); + } + + auto VulkanRenderer::current_hdri() const -> const std::string& + { + return m_impl->hdri_path; + } + auto VulkanRenderer::draw_frame(const glm::vec4& clear_color, const std::function<void()>& build_ui) -> void { Impl& v = *m_impl; diff --git a/src/platform/vulkan/vulkan_renderer.h b/src/platform/vulkan/vulkan_renderer.h index 97a4e38..68a1602 100644 --- a/src/platform/vulkan/vulkan_renderer.h +++ b/src/platform/vulkan/vulkan_renderer.h @@ -2,6 +2,7 @@ #include <glm/glm.hpp> #include <functional> +#include <string> // Live-window Vulkan backend: owns the instance, surface, device, swapchain, // render pass, framebuffers and per-frame synchronization, and drives the @@ -33,6 +34,14 @@ namespace Donut auto on_resize(int width, int height) -> void; + // Rebuilds the starfield environment cubemap from another equirect .hdr + // at runtime (device-idle teardown + rebuild + descriptor rewrite). + // No-op if path is already the active HDRI. + auto set_hdri(const std::string& path) -> void; + + // Filesystem path of the HDRI currently backing the cubemap. + auto current_hdri() const -> const std::string&; + private: struct Impl; Impl* m_impl = nullptr; |
