diff --git a/crates/egui-wgpu/CHANGELOG.md b/crates/egui-wgpu/CHANGELOG.md index d99ea1bd..424ec16c 100644 --- a/crates/egui-wgpu/CHANGELOG.md +++ b/crates/egui-wgpu/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to the `egui-wgpu` integration will be noted in this file. ## Unreleased * Add `read_screan_rgba` to the egui-wgpu `Painter`, to allow for capturing the current frame when using wgpu. Used in conjuction with `Frame::request_screenshot`. ([#2676](https://github.com/emilk/egui/pull/2676)) * Improve performance of `update_buffers` ([#2820](https://github.com/emilk/egui/pull/2820)) +* Added support for multisampling (MSAA) ([#2878](https://github.com/emilk/egui/pull/2878)) ## 0.21.0 - 2023-02-08 diff --git a/crates/egui-wgpu/src/winit.rs b/crates/egui-wgpu/src/winit.rs index d537844e..1ec4a9b7 100644 --- a/crates/egui-wgpu/src/winit.rs +++ b/crates/egui-wgpu/src/winit.rs @@ -81,6 +81,7 @@ pub struct Painter { support_transparent_backbuffer: bool, depth_format: Option, depth_texture_view: Option, + msaa_texture_view: Option, screen_capture_state: Option, instance: wgpu::Instance, @@ -125,6 +126,7 @@ impl Painter { adapter: None, render_state: None, surface_state: None, + msaa_texture_view: None, } } @@ -272,7 +274,7 @@ impl Painter { height: size.height, alpha_mode, }); - self.resize_and_generate_depth_texture_view(size.width, size.height); + self.resize_and_generate_depth_texture_view_and_msaa_view(size.width, size.height); } None => { self.surface_state = None; @@ -292,7 +294,7 @@ impl Painter { .map(|rs| rs.device.limits().max_texture_dimension_2d as usize) } - fn resize_and_generate_depth_texture_view( + fn resize_and_generate_depth_texture_view_and_msaa_view( &mut self, width_in_pixels: u32, height_in_pixels: u32, @@ -325,11 +327,38 @@ impl Painter { }) .create_view(&wgpu::TextureViewDescriptor::default()) }); + + self.msaa_texture_view = (self.msaa_samples > 1) + .then_some(self.render_state.as_ref()) + .flatten() + .map(|render_state| { + let texture_format = render_state.target_format; + render_state + .device + .create_texture(&wgpu::TextureDescriptor { + label: Some("egui_msaa_texture"), + size: wgpu::Extent3d { + width: width_in_pixels, + height: height_in_pixels, + depth_or_array_layers: 1, + }, + mip_level_count: 1, + sample_count: self.msaa_samples, + dimension: wgpu::TextureDimension::D2, + format: texture_format, + usage: wgpu::TextureUsages::RENDER_ATTACHMENT, + view_formats: &[texture_format], + }) + .create_view(&wgpu::TextureViewDescriptor::default()) + }); } pub fn on_window_resized(&mut self, width_in_pixels: u32, height_in_pixels: u32) { if self.surface_state.is_some() { - self.resize_and_generate_depth_texture_view(width_in_pixels, height_in_pixels); + self.resize_and_generate_depth_texture_view_and_msaa_view( + width_in_pixels, + height_in_pixels, + ); } else { error!("Ignoring window resize notification with no surface created via Painter::set_window()"); } @@ -522,10 +551,18 @@ impl Painter { .texture .create_view(&wgpu::TextureViewDescriptor::default()) }; + + let (view, resolve_target) = (self.msaa_samples > 1) + .then_some(self.msaa_texture_view.as_ref()) + .flatten() + .map_or((&frame_view, None), |texture_view| { + (texture_view, Some(&frame_view)) + }); + let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view: &frame_view, - resolve_target: None, + view, + resolve_target, ops: wgpu::Operations { load: wgpu::LoadOp::Clear(wgpu::Color { r: clear_color[0] as f64,