diff --git a/crates/egui-wgpu/CHANGELOG.md b/crates/egui-wgpu/CHANGELOG.md index 3983593494d..f880a9425cb 100644 --- a/crates/egui-wgpu/CHANGELOG.md +++ b/crates/egui-wgpu/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to the `egui-wgpu` integration will be noted in this file. * `Renderer` no longer handles pass creation and depth buffer creation ([#2136](https://github.com/emilk/egui/pull/2136)) * `PrepareCallback` now passes `wgpu::CommandEncoder` ([#2136](https://github.com/emilk/egui/pull/2136)) * Only a single vertex & index buffer is now created and resized when necessary (previously, vertex/index buffers were allocated for every mesh) ([#2148](https://github.com/emilk/egui/pull/2148)). +* `Renderer::update_texture` no longer creates a new `wgpu::Sampler` with every new texture ([#2198](https://github.com/emilk/egui/pull/2198)) ## 0.19.0 - 2022-08-20 * Enables deferred render + surface state initialization for Android ([#1634](https://github.com/emilk/egui/pull/1634)). diff --git a/crates/egui-wgpu/src/renderer.rs b/crates/egui-wgpu/src/renderer.rs index 0ad37720992..471dc111c65 100644 --- a/crates/egui-wgpu/src/renderer.rs +++ b/crates/egui-wgpu/src/renderer.rs @@ -130,11 +130,14 @@ pub struct Renderer { uniform_buffer: wgpu::Buffer, uniform_bind_group: wgpu::BindGroup, texture_bind_group_layout: wgpu::BindGroupLayout, + /// Map of egui texture IDs to textures and their associated bindgroups (texture view + /// sampler). The texture may be None if the TextureId is just a handle to a user-provided /// sampler. textures: HashMap, wgpu::BindGroup)>, next_user_texture_id: u64, + samplers: HashMap, + /// Storage for use by [`egui::PaintCallback`]'s that need to store resources such as render /// pipelines that must have the lifetime of the renderpass. pub paint_callback_resources: TypeMap, @@ -312,6 +315,7 @@ impl Renderer { texture_bind_group_layout, textures: HashMap::new(), next_user_texture_id: 0, + samplers: HashMap::new(), paint_callback_resources: TypeMap::default(), } } @@ -511,7 +515,6 @@ impl Renderer { origin, ); } else { - // TODO(Wumpf): Create only a new texture if we need to // allocate a new texture // Use same label for all resources associated with this texture id (no point in retyping the type) let label_str = format!("egui_texid_{:?}", id); @@ -522,20 +525,13 @@ impl Renderer { mip_level_count: 1, sample_count: 1, dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Rgba8UnormSrgb, // TODO(emilk): handle WebGL1 where this is not always supported! + format: wgpu::TextureFormat::Rgba8UnormSrgb, // Minspec for wgpu WebGL emulation is WebGL2, so this should always be supported. usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, }); - let filter = match image_delta.filter { - egui::TextureFilter::Nearest => wgpu::FilterMode::Nearest, - egui::TextureFilter::Linear => wgpu::FilterMode::Linear, - }; - // TODO(Wumpf): Reuse this sampler. - let sampler = device.create_sampler(&wgpu::SamplerDescriptor { - label, - mag_filter: filter, - min_filter: filter, - ..Default::default() - }); + let sampler = self + .samplers + .entry(image_delta.filter) + .or_insert_with(|| create_sampler(image_delta.filter, device)); let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label, layout: &self.texture_bind_group_layout, @@ -548,7 +544,7 @@ impl Renderer { }, wgpu::BindGroupEntry { binding: 1, - resource: wgpu::BindingResource::Sampler(&sampler), + resource: wgpu::BindingResource::Sampler(sampler), }, ], }); @@ -794,6 +790,19 @@ impl Renderer { } } +fn create_sampler(filter: egui::TextureFilter, device: &wgpu::Device) -> wgpu::Sampler { + let wgpu_filter = match filter { + egui::TextureFilter::Nearest => wgpu::FilterMode::Nearest, + egui::TextureFilter::Linear => wgpu::FilterMode::Linear, + }; + device.create_sampler(&wgpu::SamplerDescriptor { + label: Some(&format!("egui sampler ({:?})", filter)), + mag_filter: wgpu_filter, + min_filter: wgpu_filter, + ..Default::default() + }) +} + fn create_vertex_buffer(device: &wgpu::Device, size: u64) -> wgpu::Buffer { device.create_buffer(&wgpu::BufferDescriptor { label: Some("egui_vertex_buffer"), diff --git a/crates/epaint/src/textures.rs b/crates/epaint/src/textures.rs index 1ace2be0602..6c20d3404d5 100644 --- a/crates/epaint/src/textures.rs +++ b/crates/epaint/src/textures.rs @@ -136,7 +136,7 @@ pub struct TextureMeta { } /// How the texture texels are filtered. -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub enum TextureFilter { /// Show the nearest pixel value.