From 87f12e56fe37411068309db7d8f978035c60060d Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 17 Apr 2025 15:39:28 +0200 Subject: [PATCH] Backends: SDL_GPU: Added multi-viewport support. Amends + update example. (#8573, #8163, #7998, #7988) --- backends/imgui_impl_sdlgpu3.cpp | 25 ++++++++++++------------- docs/CHANGELOG.txt | 1 + examples/example_sdl3_sdlgpu3/main.cpp | 17 +++++++++++++++++ 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/backends/imgui_impl_sdlgpu3.cpp b/backends/imgui_impl_sdlgpu3.cpp index 96a553707..e8cc72672 100644 --- a/backends/imgui_impl_sdlgpu3.cpp +++ b/backends/imgui_impl_sdlgpu3.cpp @@ -22,6 +22,7 @@ // Calling the function is MANDATORY, otherwise the ImGui will not upload neither the vertex nor the index buffer for the GPU. See imgui_impl_sdlgpu3.cpp for more info. // CHANGELOG +// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2025-03-30: Made ImGui_ImplSDLGPU3_PrepareDrawData() reuse GPU Transfer Buffers which were unusually slow to recreate every frame. Much faster now. // 2025-03-21: Fixed typo in function name Imgui_ImplSDLGPU3_PrepareDrawData() -> ImGui_ImplSDLGPU3_PrepareDrawData(). // 2025-01-16: Renamed ImGui_ImplSDLGPU3_InitInfo::GpuDevice to Device. @@ -581,8 +582,7 @@ 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; - + io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; // We can create multi-viewports on the Renderer side (optional) IM_ASSERT(info->Device != nullptr); IM_ASSERT(info->ColorTargetFormat != SDL_GPU_TEXTUREFORMAT_INVALID); @@ -590,13 +590,11 @@ bool ImGui_ImplSDLGPU3_Init(ImGui_ImplSDLGPU3_InitInfo* info) bd->InitInfo = *info; ImGui_ImplSDLGPU3_CreateDeviceObjects(); - ImGui_ImplSDLGPU3_InitMultiViewportSupport(); return true; } - void ImGui_ImplSDLGPU3_Shutdown() { ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData(); @@ -604,7 +602,6 @@ void ImGui_ImplSDLGPU3_Shutdown() ImGuiIO& io = ImGui::GetIO(); ImGui_ImplSDLGPU3_ShutdownMultiViewportSupport(); - ImGui_ImplSDLGPU3_DestroyDeviceObjects(); io.BackendRendererName = nullptr; io.BackendRendererUserData = nullptr; @@ -627,7 +624,8 @@ void ImGui_ImplSDLGPU3_NewFrame() // 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) { +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); @@ -648,8 +646,7 @@ static void ImGui_ImplSDLGPU3_RenderWindow(ImGuiViewport* viewport, void*) if (swapchain_texture != nullptr) { - ImGui_ImplSDLGPU3_PrepareDrawData(draw_data, command_buffer); - + ImGui_ImplSDLGPU3_PrepareDrawData(draw_data, command_buffer); // FIXME-OPT: Not optimal, may this be done earlier? SDL_GPUColorTargetInfo target_info = {}; target_info.texture = swapchain_texture; target_info.clear_color = SDL_FColor{ 0.0f,0.0f,0.0f,1.0f }; @@ -659,25 +656,26 @@ static void ImGui_ImplSDLGPU3_RenderWindow(ImGuiViewport* viewport, void*) 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) { +static void ImGui_ImplSDLGPU3_DestroyWindow(ImGuiViewport* viewport) +{ ImGui_ImplSDLGPU3_Data* data = ImGui_ImplSDLGPU3_GetBackendData(); - if (viewport->RendererUserData) { + 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() { +static void ImGui_ImplSDLGPU3_InitMultiViewportSupport() +{ ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); platform_io.Renderer_RenderWindow = ImGui_ImplSDLGPU3_RenderWindow; platform_io.Renderer_CreateWindow = ImGui_ImplSDLGPU3_CreateWindow; @@ -689,5 +687,6 @@ static void ImGui_ImplSDLGPU3_ShutdownMultiViewportSupport() ImGui::DestroyPlatformWindows(); } +//----------------------------------------------------------------------------- #endif // #ifndef IMGUI_DISABLE diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a8dd700e3..54f66787f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -113,6 +113,7 @@ Docking+Viewports Branch: Because we allowed the Win32 window to close early, Windows destroyed it and our imgui window became not visible even though user code was still submitting it. +- Backends: SDLGPU3 for SDL3: added multi-viewport support. (#8573) [@Lekoopapaul] - Backends: SDL2, SDL3: revert updating monitors and work areas info every frame. Only do it on Windows to detect task-bar resize until we get an adequate event for it. (#8415, #8558) diff --git a/examples/example_sdl3_sdlgpu3/main.cpp b/examples/example_sdl3_sdlgpu3/main.cpp index 3deeeafd5..375d32cb7 100644 --- a/examples/example_sdl3_sdlgpu3/main.cpp +++ b/examples/example_sdl3_sdlgpu3/main.cpp @@ -63,11 +63,21 @@ int main(int, char**) ImGuiIO& io = ImGui::GetIO(); (void)io; io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking + io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows // Setup Dear ImGui style ImGui::StyleColorsDark(); //ImGui::StyleColorsLight(); + // When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones. + ImGuiStyle& style = ImGui::GetStyle(); + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + { + style.WindowRounding = 0.0f; + style.Colors[ImGuiCol_WindowBg].w = 1.0f; + } + // Setup Platform/Renderer backends ImGui_ImplSDL3_InitForSDLGPU(window); ImGui_ImplSDLGPU3_InitInfo init_info = {}; @@ -198,6 +208,13 @@ int main(int, char**) SDL_EndGPURenderPass(render_pass); } + // Update and Render additional Platform Windows + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) + { + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); + } + // Submit the command buffer SDL_SubmitGPUCommandBuffer(command_buffer); }