|
|
@ -19,7 +19,7 @@ use wgpu::util::DeviceExt as _; |
|
|
|
/// can issue draw commands.
|
|
|
|
///
|
|
|
|
/// The final argument of both the `prepare` and `paint` callbacks is a the
|
|
|
|
/// [`paint_callback_resources`][crate::renderer::RenderPass::paint_callback_resources].
|
|
|
|
/// [`paint_callback_resources`][crate::renderer::Renderer::paint_callback_resources].
|
|
|
|
/// `paint_callback_resources` has the same lifetime as the Egui render pass, so it can be used to
|
|
|
|
/// store buffers, pipelines, and other information that needs to be accessed during the render
|
|
|
|
/// pass.
|
|
|
@ -118,9 +118,9 @@ struct SizedBuffer { |
|
|
|
size: usize, |
|
|
|
} |
|
|
|
|
|
|
|
/// Render pass to render a egui based GUI.
|
|
|
|
pub struct RenderPass { |
|
|
|
render_pipeline: wgpu::RenderPipeline, |
|
|
|
/// Renderer for a egui based GUI.
|
|
|
|
pub struct Renderer { |
|
|
|
pipeline: wgpu::RenderPipeline, |
|
|
|
depth_texture: Option<(wgpu::Texture, wgpu::TextureView)>, |
|
|
|
index_buffers: Vec<SizedBuffer>, |
|
|
|
vertex_buffers: Vec<SizedBuffer>, |
|
|
@ -137,8 +137,8 @@ pub struct RenderPass { |
|
|
|
pub paint_callback_resources: TypeMap, |
|
|
|
} |
|
|
|
|
|
|
|
impl RenderPass { |
|
|
|
/// Creates a new render pass to render a egui UI.
|
|
|
|
impl Renderer { |
|
|
|
/// Creates a renderer for a egui UI.
|
|
|
|
///
|
|
|
|
/// If the format passed is not a *Srgb format, the shader will automatically convert to `sRGB` colors in the shader.
|
|
|
|
pub fn new( |
|
|
@ -231,7 +231,7 @@ impl RenderPass { |
|
|
|
bias: wgpu::DepthBiasState::default(), |
|
|
|
}); |
|
|
|
|
|
|
|
let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { |
|
|
|
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { |
|
|
|
label: Some("egui_pipeline"), |
|
|
|
layout: Some(&pipeline_layout), |
|
|
|
vertex: wgpu::VertexState { |
|
|
@ -290,7 +290,7 @@ impl RenderPass { |
|
|
|
}); |
|
|
|
|
|
|
|
Self { |
|
|
|
render_pipeline, |
|
|
|
pipeline, |
|
|
|
vertex_buffers: Vec::with_capacity(64), |
|
|
|
index_buffers: Vec::with_capacity(64), |
|
|
|
uniform_buffer, |
|
|
@ -323,8 +323,8 @@ impl RenderPass { |
|
|
|
self.depth_texture = Some((texture, view)); |
|
|
|
} |
|
|
|
|
|
|
|
/// Executes the egui render pass.
|
|
|
|
pub fn execute( |
|
|
|
/// Executes the renderer on its own render pass.
|
|
|
|
pub fn render( |
|
|
|
&self, |
|
|
|
encoder: &mut wgpu::CommandEncoder, |
|
|
|
color_attachment: &wgpu::TextureView, |
|
|
@ -349,7 +349,7 @@ impl RenderPass { |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { |
|
|
|
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { |
|
|
|
color_attachments: &[Some(wgpu::RenderPassColorAttachment { |
|
|
|
view: color_attachment, |
|
|
|
resolve_target: None, |
|
|
@ -359,26 +359,23 @@ impl RenderPass { |
|
|
|
}, |
|
|
|
})], |
|
|
|
depth_stencil_attachment, |
|
|
|
label: Some("egui main render pass"), |
|
|
|
label: Some("egui_render_pass"), |
|
|
|
}); |
|
|
|
rpass.push_debug_group("egui_pass"); |
|
|
|
|
|
|
|
self.execute_with_renderpass(&mut rpass, paint_jobs, screen_descriptor); |
|
|
|
|
|
|
|
rpass.pop_debug_group(); |
|
|
|
self.render_onto_renderpass(&mut render_pass, paint_jobs, screen_descriptor); |
|
|
|
} |
|
|
|
|
|
|
|
/// Executes the egui render pass onto an existing wgpu renderpass.
|
|
|
|
pub fn execute_with_renderpass<'rpass>( |
|
|
|
&'rpass self, |
|
|
|
rpass: &mut wgpu::RenderPass<'rpass>, |
|
|
|
/// Executes the egui renderer onto an existing wgpu renderpass.
|
|
|
|
pub fn render_onto_renderpass<'rp>( |
|
|
|
&'rp self, |
|
|
|
render_pass: &mut wgpu::RenderPass<'rp>, |
|
|
|
paint_jobs: &[egui::epaint::ClippedPrimitive], |
|
|
|
screen_descriptor: &ScreenDescriptor, |
|
|
|
) { |
|
|
|
let pixels_per_point = screen_descriptor.pixels_per_point; |
|
|
|
let size_in_pixels = screen_descriptor.size_in_pixels; |
|
|
|
|
|
|
|
// Whether or not we need to reset the renderpass state because a paint callback has just
|
|
|
|
// Whether or not we need to reset the render pass because a paint callback has just
|
|
|
|
// run.
|
|
|
|
let mut needs_reset = true; |
|
|
|
|
|
|
@ -391,7 +388,7 @@ impl RenderPass { |
|
|
|
} in paint_jobs |
|
|
|
{ |
|
|
|
if needs_reset { |
|
|
|
rpass.set_viewport( |
|
|
|
render_pass.set_viewport( |
|
|
|
0.0, |
|
|
|
0.0, |
|
|
|
size_in_pixels[0] as f32, |
|
|
@ -399,8 +396,8 @@ impl RenderPass { |
|
|
|
0.0, |
|
|
|
1.0, |
|
|
|
); |
|
|
|
rpass.set_pipeline(&self.render_pipeline); |
|
|
|
rpass.set_bind_group(0, &self.uniform_bind_group, &[]); |
|
|
|
render_pass.set_pipeline(&self.pipeline); |
|
|
|
render_pass.set_bind_group(0, &self.uniform_bind_group, &[]); |
|
|
|
needs_reset = false; |
|
|
|
} |
|
|
|
|
|
|
@ -417,7 +414,7 @@ impl RenderPass { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
rpass.set_scissor_rect(rect.x, rect.y, rect.width, rect.height); |
|
|
|
render_pass.set_scissor_rect(rect.x, rect.y, rect.width, rect.height); |
|
|
|
} |
|
|
|
|
|
|
|
match primitive { |
|
|
@ -426,13 +423,13 @@ impl RenderPass { |
|
|
|
let vertex_buffer = vertex_buffers.next().unwrap(); |
|
|
|
|
|
|
|
if let Some((_texture, bind_group)) = self.textures.get(&mesh.texture_id) { |
|
|
|
rpass.set_bind_group(1, bind_group, &[]); |
|
|
|
rpass.set_index_buffer( |
|
|
|
render_pass.set_bind_group(1, bind_group, &[]); |
|
|
|
render_pass.set_index_buffer( |
|
|
|
index_buffer.buffer.slice(..), |
|
|
|
wgpu::IndexFormat::Uint32, |
|
|
|
); |
|
|
|
rpass.set_vertex_buffer(0, vertex_buffer.buffer.slice(..)); |
|
|
|
rpass.draw_indexed(0..mesh.indices.len() as u32, 0, 0..1); |
|
|
|
render_pass.set_vertex_buffer(0, vertex_buffer.buffer.slice(..)); |
|
|
|
render_pass.draw_indexed(0..mesh.indices.len() as u32, 0, 0..1); |
|
|
|
} else { |
|
|
|
tracing::warn!("Missing texture: {:?}", mesh.texture_id); |
|
|
|
} |
|
|
@ -461,7 +458,7 @@ impl RenderPass { |
|
|
|
let rect_max_x = rect_max_x.round(); |
|
|
|
let rect_max_y = rect_max_y.round(); |
|
|
|
|
|
|
|
rpass.set_viewport( |
|
|
|
render_pass.set_viewport( |
|
|
|
rect_min_x, |
|
|
|
rect_min_y, |
|
|
|
rect_max_x - rect_min_x, |
|
|
@ -478,7 +475,7 @@ impl RenderPass { |
|
|
|
pixels_per_point, |
|
|
|
screen_size_px: size_in_pixels, |
|
|
|
}, |
|
|
|
rpass, |
|
|
|
render_pass, |
|
|
|
&self.paint_callback_resources, |
|
|
|
); |
|
|
|
} |
|
|
@ -486,10 +483,10 @@ impl RenderPass { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
rpass.set_scissor_rect(0, 0, size_in_pixels[0], size_in_pixels[1]); |
|
|
|
render_pass.set_scissor_rect(0, 0, size_in_pixels[0], size_in_pixels[1]); |
|
|
|
} |
|
|
|
|
|
|
|
/// Should be called before `execute()`.
|
|
|
|
/// Should be called before `render()`.
|
|
|
|
pub fn update_texture( |
|
|
|
&mut self, |
|
|
|
device: &wgpu::Device, |
|
|
@ -768,8 +765,8 @@ impl RenderPass { |
|
|
|
*user_texture_binding = bind_group; |
|
|
|
} |
|
|
|
|
|
|
|
/// Uploads the uniform, vertex and index data used by the render pass.
|
|
|
|
/// Should be called before `execute()`.
|
|
|
|
/// Uploads the uniform, vertex and index data used by the renderer.
|
|
|
|
/// Should be called before `render()`.
|
|
|
|
pub fn update_buffers( |
|
|
|
&mut self, |
|
|
|
device: &wgpu::Device, |
|
|
@ -922,7 +919,7 @@ impl ScissorRect { |
|
|
|
} |
|
|
|
|
|
|
|
#[test] |
|
|
|
fn render_pass_impl_send_sync() { |
|
|
|
fn renderer_impl_send_sync() { |
|
|
|
fn assert_send_sync<T: Send + Sync>() {} |
|
|
|
assert_send_sync::<RenderPass>(); |
|
|
|
assert_send_sync::<Renderer>(); |
|
|
|
} |
|
|
|