Skip to content

Commit

Permalink
Add Options::reduce_texture_memory to free up RAM (emilk#4431)
Browse files Browse the repository at this point in the history
## 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.
  • Loading branch information
varphone authored and hacknus committed Oct 30, 2024
1 parent 45a550b commit 7e6505d
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 0 deletions.
11 changes: 11 additions & 0 deletions crates/egui/src/load/texture_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 })
}
}
Expand Down
17 changes: 17 additions & 0 deletions crates/egui/src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -260,6 +273,7 @@ impl Default for Options {
// Input:
line_scroll_speed,
scroll_zoom_speed: 1.0 / 200.0,
reduce_texture_memory: false,
}
}
}
Expand All @@ -279,6 +293,7 @@ impl Options {

line_scroll_speed,
scroll_zoom_speed,
reduce_texture_memory,
} = self;

use crate::Widget as _;
Expand All @@ -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::*;
Expand Down
5 changes: 5 additions & 0 deletions crates/egui_demo_app/src/apps/image_viewer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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| {
Expand Down

0 comments on commit 7e6505d

Please sign in to comment.