Browse Source

wgpu renderer no longer creates a sampler with every texture (#2198)

pull/2200/head
Andreas Reich 2 years ago
committed by GitHub
parent
commit
53b800502a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      crates/egui-wgpu/CHANGELOG.md
  2. 37
      crates/egui-wgpu/src/renderer.rs
  3. 2
      crates/epaint/src/textures.rs

1
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)) * `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)) * `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)). * 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 ## 0.19.0 - 2022-08-20
* Enables deferred render + surface state initialization for Android ([#1634](https://github.com/emilk/egui/pull/1634)). * Enables deferred render + surface state initialization for Android ([#1634](https://github.com/emilk/egui/pull/1634)).

37
crates/egui-wgpu/src/renderer.rs

@ -130,11 +130,14 @@ pub struct Renderer {
uniform_buffer: wgpu::Buffer, uniform_buffer: wgpu::Buffer,
uniform_bind_group: wgpu::BindGroup, uniform_bind_group: wgpu::BindGroup,
texture_bind_group_layout: wgpu::BindGroupLayout, texture_bind_group_layout: wgpu::BindGroupLayout,
/// Map of egui texture IDs to textures and their associated bindgroups (texture view + /// 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). The texture may be None if the TextureId is just a handle to a user-provided
/// sampler. /// sampler.
textures: HashMap<egui::TextureId, (Option<wgpu::Texture>, wgpu::BindGroup)>, textures: HashMap<egui::TextureId, (Option<wgpu::Texture>, wgpu::BindGroup)>,
next_user_texture_id: u64, next_user_texture_id: u64,
samplers: HashMap<egui::TextureFilter, wgpu::Sampler>,
/// Storage for use by [`egui::PaintCallback`]'s that need to store resources such as render /// Storage for use by [`egui::PaintCallback`]'s that need to store resources such as render
/// pipelines that must have the lifetime of the renderpass. /// pipelines that must have the lifetime of the renderpass.
pub paint_callback_resources: TypeMap, pub paint_callback_resources: TypeMap,
@ -312,6 +315,7 @@ impl Renderer {
texture_bind_group_layout, texture_bind_group_layout,
textures: HashMap::new(), textures: HashMap::new(),
next_user_texture_id: 0, next_user_texture_id: 0,
samplers: HashMap::new(),
paint_callback_resources: TypeMap::default(), paint_callback_resources: TypeMap::default(),
} }
} }
@ -511,7 +515,6 @@ impl Renderer {
origin, origin,
); );
} else { } else {
// TODO(Wumpf): Create only a new texture if we need to
// allocate a new texture // allocate a new texture
// Use same label for all resources associated with this texture id (no point in retyping the type) // Use same label for all resources associated with this texture id (no point in retyping the type)
let label_str = format!("egui_texid_{:?}", id); let label_str = format!("egui_texid_{:?}", id);
@ -522,20 +525,13 @@ impl Renderer {
mip_level_count: 1, mip_level_count: 1,
sample_count: 1, sample_count: 1,
dimension: wgpu::TextureDimension::D2, 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, usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
}); });
let filter = match image_delta.filter { let sampler = self
egui::TextureFilter::Nearest => wgpu::FilterMode::Nearest, .samplers
egui::TextureFilter::Linear => wgpu::FilterMode::Linear, .entry(image_delta.filter)
}; .or_insert_with(|| create_sampler(image_delta.filter, device));
// TODO(Wumpf): Reuse this sampler.
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
label,
mag_filter: filter,
min_filter: filter,
..Default::default()
});
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label, label,
layout: &self.texture_bind_group_layout, layout: &self.texture_bind_group_layout,
@ -548,7 +544,7 @@ impl Renderer {
}, },
wgpu::BindGroupEntry { wgpu::BindGroupEntry {
binding: 1, 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 { fn create_vertex_buffer(device: &wgpu::Device, size: u64) -> wgpu::Buffer {
device.create_buffer(&wgpu::BufferDescriptor { device.create_buffer(&wgpu::BufferDescriptor {
label: Some("egui_vertex_buffer"), label: Some("egui_vertex_buffer"),

2
crates/epaint/src/textures.rs

@ -136,7 +136,7 @@ pub struct TextureMeta {
} }
/// How the texture texels are filtered. /// 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))] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum TextureFilter { pub enum TextureFilter {
/// Show the nearest pixel value. /// Show the nearest pixel value.

Loading…
Cancel
Save