diff --git a/src/core/fullscreenui_widgets.cpp b/src/core/fullscreenui_widgets.cpp index 4c4b8fea0..f37fb50f8 100644 --- a/src/core/fullscreenui_widgets.cpp +++ b/src/core/fullscreenui_widgets.cpp @@ -113,7 +113,7 @@ static void PostDrawMenuButtonFrame(); static void DrawBackgroundProgressDialogs(float& current_y); static void UpdateLoadingScreenProgress(s32 progress_min, s32 progress_max, s32 progress_value); static bool GetLoadingScreenTimeEstimate(SmallString& out_str); -static void DrawLoadingScreen(std::string_view image, std::string_view title, std::string_view caption, +static void DrawLoadingScreen(ImDrawList* dl, std::string_view image, std::string_view title, std::string_view caption, s32 progress_min, s32 progress_max, s32 progress_value, bool is_persistent); // Returns true if any overlay windows are active, such as notifications or toasts. @@ -6662,13 +6662,24 @@ void FullscreenUI::RenderLoadingScreen(std::string_view image, std::string_view if (!g_gpu_device || !g_gpu_device->HasMainSwapChain()) return; - // eat the last imgui frame, it might've been partially rendered by the caller. - ImGui::EndFrame(); - ImGui::NewFrame(); - - DrawLoadingScreen(image, title, caption, progress_min, progress_max, progress_value, false); - - ImGuiManager::CreateDrawLists(); + // Use a separate draw list for the loading screen, that way we don't mess with the main ImGui state. + // Otherwise window would get GC/reset, etc. + const ImGuiIO& io = ImGui::GetIO(); + ImDrawList draw_list(ImGui::GetDrawListSharedData()); + draw_list._OwnerName = "##LoadingScreen"; + draw_list._ResetForNewFrame(); + draw_list.PushTexture(io.Fonts->TexRef); + draw_list.PushClipRect(ImVec2(), io.DisplaySize, false); + + DrawLoadingScreen(&draw_list, image, title, caption, progress_min, progress_max, progress_value, false); + + ImDrawData draw_data; + draw_data.Valid = true; + draw_data.DisplaySize = io.DisplaySize; + draw_data.FramebufferScale = io.DisplayFramebufferScale; + draw_data.OwnerViewport = ImGui::GetMainViewport(); + draw_data.Textures = &io.Fonts->TexList; + draw_data.AddDrawList(&draw_list); if (s_state.blur_active && !s_state.blur_valid) { @@ -6683,11 +6694,9 @@ void FullscreenUI::RenderLoadingScreen(std::string_view image, std::string_view GPUSwapChain* swap_chain = g_gpu_device->GetMainSwapChain(); if (g_gpu_device->BeginPresent(swap_chain) == GPUPresentResult::OK) { - ImGuiManager::RenderDrawLists(swap_chain); + ImGuiManager::RenderDrawLists(&draw_data, swap_chain); g_gpu_device->EndPresent(swap_chain, false); } - - ImGuiManager::NewFrame(Timer::GetCurrentValue()); } void FullscreenUI::UpdateLoadingScreenRunIdle() @@ -6747,8 +6756,9 @@ void FullscreenUI::DrawLoadingScreen() if (!s_state.loading_screen_open) return; - DrawLoadingScreen(s_state.loading_screen_image, s_state.loading_screen_title, s_state.loading_screen_caption, - s_state.loading_screen_min, s_state.loading_screen_max, s_state.loading_screen_value, true); + DrawLoadingScreen(ImGui::GetBackgroundDrawList(), s_state.loading_screen_image, s_state.loading_screen_title, + s_state.loading_screen_caption, s_state.loading_screen_min, s_state.loading_screen_max, + s_state.loading_screen_value, true); } void FullscreenUI::CloseLoadingScreen() @@ -6841,8 +6851,9 @@ bool FullscreenUI::GetLoadingScreenTimeEstimate(SmallString& out_str) return true; } -void FullscreenUI::DrawLoadingScreen(std::string_view image, std::string_view title, std::string_view caption, - s32 progress_min, s32 progress_max, s32 progress_value, bool is_persistent) +void FullscreenUI::DrawLoadingScreen(ImDrawList* dl, std::string_view image, std::string_view title, + std::string_view caption, s32 progress_min, s32 progress_max, s32 progress_value, + bool is_persistent) { const auto& io = ImGui::GetIO(); const bool has_progress = (progress_min < progress_max); @@ -6889,8 +6900,6 @@ void FullscreenUI::DrawLoadingScreen(std::string_view image, std::string_view ti (has_progress ? (item_spacing + estimate_font_size) : 0.0f); const ImVec2 image_pos = ImVec2(ImCeil((io.DisplaySize.x - image_width) * 0.5f), ImCeil(((io.DisplaySize.y - total_height) * 0.5f))); - ImDrawList* const dl = ImGui::GetBackgroundDrawList(); - if (VideoPresenter::HasDisplayTexture()) { if (UIStyle.BlurMenuBackground && BeginBlurBackground(dl, ImVec2(), io.DisplaySize)) diff --git a/src/core/video_presenter.cpp b/src/core/video_presenter.cpp index 6310354ec..987fbd825 100644 --- a/src/core/video_presenter.cpp +++ b/src/core/video_presenter.cpp @@ -1537,7 +1537,7 @@ bool VideoPresenter::PresentFrame(GPUBackend* backend, u64 present_time) } g_gpu_device->SetRenderTarget(transition_target); - ImGuiManager::RenderDrawLists(transition_target); + ImGuiManager::RenderDrawLists(ImGui::GetDrawData(), transition_target); if ((pres = g_gpu_device->BeginPresent(swap_chain)) == GPUPresentResult::OK) FullscreenUI::RenderTransitionBlend(swap_chain, transition_target); @@ -1547,7 +1547,7 @@ bool VideoPresenter::PresentFrame(GPUBackend* backend, u64 present_time) if ((pres = blur_target ? DrawDisplayCopy(blur_target, nullptr, swap_chain) : RenderDisplay(nullptr, swap_chain->GetSizeVec(), true, true)) == GPUPresentResult::OK) { - ImGuiManager::RenderDrawLists(swap_chain); + ImGuiManager::RenderDrawLists(ImGui::GetDrawData(), swap_chain); } } diff --git a/src/util/imgui_manager.cpp b/src/util/imgui_manager.cpp index e68a5f5f0..bfbe7f700 100644 --- a/src/util/imgui_manager.cpp +++ b/src/util/imgui_manager.cpp @@ -97,8 +97,9 @@ static bool LoadFontData(Error* error); static void ReloadFontDataIfActive(); static bool CreateFontAtlas(Error* error); static bool CompilePipelines(Error* error); -static void RenderDrawLists(u32 window_width, u32 window_height, WindowInfoPrerotation prerotation); -static void UpdateTextures(); +static void RenderDrawLists(const ImDrawData* draw_data, u32 window_width, u32 window_height, + WindowInfoPrerotation prerotation); +static void UpdateTextures(const ImDrawData* draw_data); static void DestroyTextures(bool recycle); static void SetCommonIOOptions(ImGuiIO& io, ImGuiPlatformIO& pio); static void SetImKeyState(ImGuiIO& io, ImGuiKey imkey, bool pressed); @@ -621,12 +622,14 @@ void ImGuiManager::CreateDrawLists() { ImGui::EndFrame(); ImGui::Render(); - UpdateTextures(); + UpdateTextures(ImGui::GetDrawData()); } -void ImGuiManager::RenderDrawLists(u32 window_width, u32 window_height, WindowInfoPrerotation prerotation) +void ImGuiManager::RenderDrawLists(const ImDrawData* draw_data, u32 window_width, u32 window_height, + WindowInfoPrerotation prerotation) { - const ImDrawData* draw_data = ImGui::GetDrawData(); + UpdateTextures(draw_data); + if (draw_data->CmdListsCount == 0) return; @@ -691,19 +694,19 @@ void ImGuiManager::RenderDrawLists(u32 window_width, u32 window_height, WindowIn } } -void ImGuiManager::RenderDrawLists(GPUSwapChain* swap_chain) +void ImGuiManager::RenderDrawLists(const ImDrawData* draw_data, GPUSwapChain* swap_chain) { - RenderDrawLists(swap_chain->GetWidth(), swap_chain->GetHeight(), swap_chain->GetPreRotation()); + RenderDrawLists(draw_data, swap_chain->GetWidth(), swap_chain->GetHeight(), swap_chain->GetPreRotation()); } -void ImGuiManager::RenderDrawLists(GPUTexture* texture) +void ImGuiManager::RenderDrawLists(const ImDrawData* draw_data, GPUTexture* texture) { - RenderDrawLists(texture->GetWidth(), texture->GetHeight(), WindowInfoPrerotation::Identity); + RenderDrawLists(draw_data, texture->GetWidth(), texture->GetHeight(), WindowInfoPrerotation::Identity); } -void ImGuiManager::UpdateTextures() +void ImGuiManager::UpdateTextures(const ImDrawData* draw_data) { - for (ImTextureData* const tex : s_state.imgui_context->IO.Fonts->TexList) + for (ImTextureData* const tex : *draw_data->Textures) { switch (tex->Status) { @@ -2225,7 +2228,7 @@ bool ImGuiManager::RenderAuxiliaryRenderWindow(AuxiliaryRenderWindowState* state const GPUPresentResult pres = g_gpu_device->BeginPresent(state->swap_chain.get()); if (pres == GPUPresentResult::OK) { - RenderDrawLists(state->swap_chain.get()); + RenderDrawLists(ImGui::GetDrawData(), state->swap_chain.get()); g_gpu_device->EndPresent(state->swap_chain.get(), false); } diff --git a/src/util/imgui_manager.h b/src/util/imgui_manager.h index c9f1ef0b6..aac7237dd 100644 --- a/src/util/imgui_manager.h +++ b/src/util/imgui_manager.h @@ -19,6 +19,7 @@ class GPUTexture; enum class GPUTextureFormat : u8; struct ImGuiContext; +struct ImDrawData; struct ImFont; union InputBindingKey; @@ -144,8 +145,8 @@ void NewFrame(u64 current_time); void CreateDrawLists(); /// Renders ImGui screen elements. Call before EndPresent(). -void RenderDrawLists(GPUSwapChain* swap_chain); -void RenderDrawLists(GPUTexture* texture); +void RenderDrawLists(const ImDrawData* draw_data, GPUSwapChain* swap_chain); +void RenderDrawLists(const ImDrawData* draw_data, GPUTexture* texture); /// Renders any on-screen display elements. void RenderOSDMessages();