From baffc4e8b871132cc35903e599ac02619896a78c Mon Sep 17 00:00:00 2001 From: Lekoopapaul Date: Tue, 15 Apr 2025 20:45:18 +0200 Subject: [PATCH] Backends: SDL_GPU: Added multi-viewport support. (#8573, #8163, #7998, #7988) --- backends/imgui_impl_sdlgpu3.cpp | 82 ++++++++++++++++++++++++++++++++- backends/imgui_impl_sdlgpu3.h | 3 +- 2 files changed, 81 insertions(+), 4 deletions(-) diff --git a/backends/imgui_impl_sdlgpu3.cpp b/backends/imgui_impl_sdlgpu3.cpp index 1cf839f32..96a553707 100644 --- a/backends/imgui_impl_sdlgpu3.cpp +++ b/backends/imgui_impl_sdlgpu3.cpp @@ -4,8 +4,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use simply cast a reference to your SDL_GPUTextureSamplerBinding to ImTextureID. // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. -// Missing features: -// [ ] Renderer: Multi-viewport support (multiple windows). +// [X] Renderer: Multi-viewport support (multiple windows). // The aim of imgui_impl_sdlgpu3.h/.cpp is to be usable in your engine without any modification. // IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/ @@ -568,6 +567,9 @@ void ImGui_ImplSDLGPU3_DestroyDeviceObjects() if (bd->Pipeline) { SDL_ReleaseGPUGraphicsPipeline(v->Device, bd->Pipeline); bd->Pipeline = nullptr;} } +static void ImGui_ImplSDLGPU3_InitMultiViewportSupport(); +static void ImGui_ImplSDLGPU3_ShutdownMultiViewportSupport(); + bool ImGui_ImplSDLGPU3_Init(ImGui_ImplSDLGPU3_InitInfo* info) { ImGuiIO& io = ImGui::GetIO(); @@ -579,6 +581,8 @@ bool ImGui_ImplSDLGPU3_Init(ImGui_ImplSDLGPU3_InitInfo* info) io.BackendRendererUserData = (void*)bd; io.BackendRendererName = "imgui_impl_sdlgpu3"; io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. + io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; + IM_ASSERT(info->Device != nullptr); IM_ASSERT(info->ColorTargetFormat != SDL_GPU_TEXTUREFORMAT_INVALID); @@ -587,15 +591,20 @@ bool ImGui_ImplSDLGPU3_Init(ImGui_ImplSDLGPU3_InitInfo* info) ImGui_ImplSDLGPU3_CreateDeviceObjects(); + ImGui_ImplSDLGPU3_InitMultiViewportSupport(); + return true; } + void ImGui_ImplSDLGPU3_Shutdown() { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ImGui_ImplSDLGPU3_ShutdownMultiViewportSupport(); + ImGui_ImplSDLGPU3_DestroyDeviceObjects(); io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; @@ -612,4 +621,73 @@ void ImGui_ImplSDLGPU3_NewFrame() ImGui_ImplSDLGPU3_CreateFontsTexture(); } +//-------------------------------------------------------------------------------------------------------- +// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT +// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously. +// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first.. +//-------------------------------------------------------------------------------------------------------- + +static void ImGui_ImplSDLGPU3_CreateWindow(ImGuiViewport* viewport) { + ImGui_ImplSDLGPU3_Data* data = ImGui_ImplSDLGPU3_GetBackendData(); + SDL_Window* window = SDL_GetWindowFromID((SDL_WindowID)(intptr_t)viewport->PlatformHandle); + SDL_ClaimWindowForGPUDevice(data->InitInfo.Device, window); + viewport->RendererUserData = (void*)1; +} + +static void ImGui_ImplSDLGPU3_RenderWindow(ImGuiViewport* viewport, void*) +{ + ImGui_ImplSDLGPU3_Data* data = ImGui_ImplSDLGPU3_GetBackendData(); + SDL_Window* window = SDL_GetWindowFromID((SDL_WindowID)(intptr_t)viewport->PlatformHandle); + + ImDrawData* draw_data = viewport->DrawData; + + SDL_GPUCommandBuffer* command_buffer = SDL_AcquireGPUCommandBuffer(data->InitInfo.Device); + + SDL_GPUTexture* swapchain_texture; + SDL_AcquireGPUSwapchainTexture(command_buffer, window, &swapchain_texture, nullptr, nullptr); + + if (swapchain_texture != nullptr) + { + ImGui_ImplSDLGPU3_PrepareDrawData(draw_data, command_buffer); + + SDL_GPUColorTargetInfo target_info = {}; + target_info.texture = swapchain_texture; + target_info.clear_color = SDL_FColor{ 0.0f,0.0f,0.0f,1.0f }; + target_info.load_op = SDL_GPU_LOADOP_CLEAR; + target_info.store_op = SDL_GPU_STOREOP_STORE; + target_info.mip_level = 0; + target_info.layer_or_depth_plane = 0; + target_info.cycle = false; + SDL_GPURenderPass* render_pass = SDL_BeginGPURenderPass(command_buffer, &target_info, 1, nullptr); + + ImGui_ImplSDLGPU3_RenderDrawData(draw_data, command_buffer, render_pass); + + SDL_EndGPURenderPass(render_pass); + } + + SDL_SubmitGPUCommandBuffer(command_buffer); +} + +static void ImGui_ImplSDLGPU3_DestroyWindow(ImGuiViewport* viewport) { + ImGui_ImplSDLGPU3_Data* data = ImGui_ImplSDLGPU3_GetBackendData(); + if (viewport->RendererUserData) { + SDL_Window* window = SDL_GetWindowFromID((SDL_WindowID)(intptr_t)viewport->PlatformHandle); + SDL_ReleaseWindowFromGPUDevice(data->InitInfo.Device, window); + } + viewport->RendererUserData = nullptr; +} + +static void ImGui_ImplSDLGPU3_InitMultiViewportSupport() { + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + platform_io.Renderer_RenderWindow = ImGui_ImplSDLGPU3_RenderWindow; + platform_io.Renderer_CreateWindow = ImGui_ImplSDLGPU3_CreateWindow; + platform_io.Renderer_DestroyWindow = ImGui_ImplSDLGPU3_DestroyWindow; +} + +static void ImGui_ImplSDLGPU3_ShutdownMultiViewportSupport() +{ + ImGui::DestroyPlatformWindows(); +} + + #endif // #ifndef IMGUI_DISABLE diff --git a/backends/imgui_impl_sdlgpu3.h b/backends/imgui_impl_sdlgpu3.h index 63691dd65..13e7497e6 100644 --- a/backends/imgui_impl_sdlgpu3.h +++ b/backends/imgui_impl_sdlgpu3.h @@ -4,8 +4,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use simply cast a reference to your SDL_GPUTextureSamplerBinding to ImTextureID. // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. -// Missing features: -// [ ] Renderer: Multi-viewport support (multiple windows). +// [X] Renderer: Multi-viewport support (multiple windows). // The aim of imgui_impl_sdlgpu3.h/.cpp is to be usable in your engine without any modification. // IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/