FullscreenUI: Render loading screen with separate draw list

Avoids disturbing the main ImGui state.
pull/3782/head
Stenzek 1 month ago
parent 24deeeef84
commit 56226045db
No known key found for this signature in database

@ -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))

@ -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);
}
}

@ -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);
}

@ -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();

Loading…
Cancel
Save