From 6f59a14c4d834c0c2df4f576b025c2297815e1d8 Mon Sep 17 00:00:00 2001 From: Varphone Wong Date: Tue, 28 May 2024 15:13:43 +0800 Subject: [PATCH] Add `Options::reduce_texture_memory` to free up RAM (#4431) ## Summary This PR introduces a new configuration option `reduce_texture_memory` in `egui`. ## Changes - Added `reduce_texture_memory` option in `egui`. When set to `true`, `egui` will discard the loaded image data after the texture is uploaded to the GPU, reducing memory usage. This is beneficial when handling a large number of images and retaining the image data is unnecessary, potentially saving substantial memory. However, this makes it impossible to serialize the loaded images or render on non-GPU systems. Default is `false`. ## Impact This new configuration option gives users more control over their memory usage, especially when dealing with a large number or large resolution of images. It allows users to optimize their applications based on their specific needs and constraints. --- crates/egui/src/load/texture_loader.rs | 11 +++++++++++ crates/egui/src/memory.rs | 17 +++++++++++++++++ crates/egui_demo_app/src/apps/image_viewer.rs | 5 +++++ 3 files changed, 33 insertions(+) diff --git a/crates/egui/src/load/texture_loader.rs b/crates/egui/src/load/texture_loader.rs index 89d616e4760..26c254d4d0b 100644 --- a/crates/egui/src/load/texture_loader.rs +++ b/crates/egui/src/load/texture_loader.rs @@ -28,6 +28,17 @@ impl TextureLoader for DefaultTextureLoader { let handle = ctx.load_texture(uri, image, texture_options); let texture = SizedTexture::from_handle(&handle); cache.insert((uri.into(), texture_options), handle); + let reduce_texture_memory = ctx.options(|o| o.reduce_texture_memory); + if reduce_texture_memory { + let loaders = ctx.loaders(); + loaders.include.forget(uri); + for loader in loaders.bytes.lock().iter().rev() { + loader.forget(uri); + } + for loader in loaders.image.lock().iter().rev() { + loader.forget(uri); + } + } Ok(TexturePoll::Ready { texture }) } } diff --git a/crates/egui/src/memory.rs b/crates/egui/src/memory.rs index 8a642adf28e..ed2a7024ba1 100644 --- a/crates/egui/src/memory.rs +++ b/crates/egui/src/memory.rs @@ -235,6 +235,19 @@ pub struct Options { /// Controls the speed at which we zoom in when doing ctrl/cmd + scroll. pub scroll_zoom_speed: f32, + + /// If `true`, `egui` will discard the loaded image data after + /// the texture is loaded onto the GPU to reduce memory usage. + /// + /// In modern GPU rendering, the texture data is not required after the texture is loaded. + /// + /// This is beneficial when using a large number or resolution of images and there is no need to + /// retain the image data, potentially saving a significant amount of memory. + /// + /// The drawback is that it becomes impossible to serialize the loaded images or render in non-GPU systems. + /// + /// Default is `false`. + pub reduce_texture_memory: bool, } impl Default for Options { @@ -260,6 +273,7 @@ impl Default for Options { // Input: line_scroll_speed, scroll_zoom_speed: 1.0 / 200.0, + reduce_texture_memory: false, } } } @@ -279,6 +293,7 @@ impl Options { line_scroll_speed, scroll_zoom_speed, + reduce_texture_memory, } = self; use crate::Widget as _; @@ -297,6 +312,8 @@ impl Options { ); ui.checkbox(warn_on_id_clash, "Warn if two widgets have the same Id"); + + ui.checkbox(reduce_texture_memory, "Reduce texture memory"); }); use crate::containers::*; diff --git a/crates/egui_demo_app/src/apps/image_viewer.rs b/crates/egui_demo_app/src/apps/image_viewer.rs index cd834424aa2..ad7a8448640 100644 --- a/crates/egui_demo_app/src/apps/image_viewer.rs +++ b/crates/egui_demo_app/src/apps/image_viewer.rs @@ -184,6 +184,11 @@ impl eframe::App for ImageViewer { ui.add_space(5.0); ui.label("Aspect ratio is maintained by scaling both sides as necessary"); ui.checkbox(&mut self.maintain_aspect_ratio, "Maintain aspect ratio"); + + // forget all images + if ui.button("Forget all images").clicked() { + ui.ctx().forget_all_images(); + } }); egui::CentralPanel::default().show(ctx, |ui| {