diff --git a/src/core/fullscreenui.cpp b/src/core/fullscreenui.cpp index 7c7b4d323..a9d1e608d 100644 --- a/src/core/fullscreenui.cpp +++ b/src/core/fullscreenui.cpp @@ -1893,10 +1893,7 @@ bool FullscreenUI::InitializeSaveStateListEntryFromPath(SaveStateListEntry* li, void FullscreenUI::ClearSaveStateEntryList() { for (SaveStateListEntry& entry : s_locals.save_state_selector_slots) - { - if (entry.preview_texture) - g_gpu_device->RecycleTexture(std::move(entry.preview_texture)); - } + QueueTextureRecycle(std::move(entry.preview_texture)); s_locals.save_state_selector_slots.clear(); } @@ -1993,10 +1990,8 @@ void FullscreenUI::DrawSaveStateSelector() [global = entry.global, slot = entry.slot]() { System::LoadStateFromSlot(global, slot); }); } - BeginTransition(TransitionEffect::Fade, LONG_TRANSITION_TIME, []() { - ClearSaveStateEntryList(); // entry no longer valid - ClosePauseMenu(TransitionEffect::None); - }); + ClearSaveStateEntryList(); + ClosePauseMenu(TransitionEffect::Fade, LONG_TRANSITION_TIME); } else { @@ -2006,11 +2001,8 @@ void FullscreenUI::DrawSaveStateSelector() static constexpr auto do_save_state = [](const SaveStateListEntry& entry) { Host::RunOnCoreThread([slot = entry.slot, global = entry.global]() { System::SaveStateToSlot(global, slot); }); - - BeginTransition(TransitionEffect::Fade, LONG_TRANSITION_TIME, []() { - ClearSaveStateEntryList(); // entry no longer valid - ClosePauseMenu(TransitionEffect::None); - }); + ClearSaveStateEntryList(); + ClosePauseMenu(TransitionEffect::Fade, LONG_TRANSITION_TIME); }; ImGuiIO& io = ImGui::GetIO(); @@ -2171,8 +2163,7 @@ void FullscreenUI::DrawSaveStateSelector() ShowToast(OSDMessageType::Quick, {}, fmt::format(FSUI_FSTR("{} deleted."), RemoveHash(entry.title))); // need to preserve the texture, since it's going to be drawn this frame - // TODO: do this with a transition for safety - g_gpu_device->RecycleTexture(std::move(entry.preview_texture)); + QueueTextureRecycle(std::move(entry.preview_texture)); if (s_locals.save_state_selector_loading) { @@ -2247,10 +2238,8 @@ void FullscreenUI::DrawSaveStateSelector() } else if ((!AreAnyDialogsOpen() && WantsToCloseMenu()) || closed) { - BeginTransition(TransitionEffect::ZoomOut, DEFAULT_TRANSITION_TIME, []() { - ClearSaveStateEntryList(); - ReturnToPreviousWindow(TransitionEffect::None); - }); + ClearSaveStateEntryList(); + ReturnToPreviousWindow(TransitionEffect::ZoomOut); } } diff --git a/src/core/fullscreenui_widgets.cpp b/src/core/fullscreenui_widgets.cpp index 2fa68dc2a..ddfe8637f 100644 --- a/src/core/fullscreenui_widgets.cpp +++ b/src/core/fullscreenui_widgets.cpp @@ -442,6 +442,7 @@ struct WidgetsState LRUCache> texture_cache{128, true}; std::shared_ptr placeholder_texture; std::deque> texture_upload_queue; + std::vector> texture_recycle_queue; // Transition Resources TransitionStartCallback transition_start_callback; @@ -647,6 +648,8 @@ bool FullscreenUI::CreateWidgetsGPUResources(Error* error) void FullscreenUI::DestroyWidgetsGPUResources() { + RecycleQueuedTextures(); + g_gpu_device->RecycleTexture(std::move(s_state.blur_source_texture)); g_gpu_device->RecycleTexture(std::move(s_state.blur_intermediate_texture)); g_gpu_device->RecycleTexture(std::move(s_state.blur_output_texture)); @@ -1074,6 +1077,19 @@ void FullscreenUI::UploadAsyncTextures() } } +void FullscreenUI::QueueTextureRecycle(std::unique_ptr texture) +{ + if (texture) + s_state.texture_recycle_queue.push_back(std::move(texture)); +} + +void FullscreenUI::RecycleQueuedTextures() +{ + for (std::unique_ptr& tex : s_state.texture_recycle_queue) + g_gpu_device->RecycleTexture(std::move(tex)); + s_state.texture_recycle_queue.clear(); +} + void FullscreenUI::BeginTransition(TransitionStartCallback func, float time) { BeginTransition(TransitionEffect::Fade, time, std::move(func)); diff --git a/src/core/fullscreenui_widgets.h b/src/core/fullscreenui_widgets.h index 346d26d4d..e94f3c2e8 100644 --- a/src/core/fullscreenui_widgets.h +++ b/src/core/fullscreenui_widgets.h @@ -275,6 +275,8 @@ GPUTexture* GetCachedTextureAsync(std::string_view name, const ImVec2& size); bool InvalidateCachedTexture(std::string_view path); bool TextureNeedsSVGDimensions(std::string_view path); void UploadAsyncTextures(); +void QueueTextureRecycle(std::unique_ptr texture); +void RecycleQueuedTextures(); /// Screen transitions. inline constexpr float SHORT_TRANSITION_TIME = 0.15f; diff --git a/src/core/video_presenter.cpp b/src/core/video_presenter.cpp index 49cbd29a4..5e81ad949 100644 --- a/src/core/video_presenter.cpp +++ b/src/core/video_presenter.cpp @@ -1551,6 +1551,8 @@ bool VideoPresenter::PresentFrame(GPUBackend* backend, u64 present_time) } } + FullscreenUI::RecycleQueuedTextures(); + if (pres == GPUPresentResult::OK) { const GPUDevice::Features features = g_gpu_device->GetFeatures();