From 346dcdf6dbf8360c5959c4f84e1ff8e83a7ed142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C4=93teris=20Pakalns?= Date: Tue, 27 Aug 2024 14:56:29 +0300 Subject: [PATCH 1/2] Support executing additional render passes or adding command buffers from paint callback --- src/egui_node.rs | 69 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 15 deletions(-) diff --git a/src/egui_node.rs b/src/egui_node.rs index 0966e35e..086ed201 100644 --- a/src/egui_node.rs +++ b/src/egui_node.rs @@ -382,11 +382,11 @@ impl Node for EguiNode { } } - fn run( + fn run<'w>( &self, _graph: &mut RenderGraphContext, - render_context: &mut RenderContext, - world: &World, + render_context: &mut RenderContext<'w>, + world: &'w World, ) -> Result<(), NodeRunError> { let egui_pipelines = &world.get_resource::().unwrap().0; let pipeline_cache = world.get_resource::().unwrap(); @@ -409,6 +409,40 @@ impl Node for EguiNode { render_queue.write_buffer(vertex_buffer, 0, &self.vertex_data); render_queue.write_buffer(index_buffer, 0, &self.index_data); + let (physical_width, physical_height, pipeline_key) = match extracted_window { + Some(window) => ( + window.physical_width, + window.physical_height, + EguiPipelineKey::from_extracted_window(window), + ), + None => unreachable!(), + }; + let Some(key) = pipeline_key else { + return Ok(()); + }; + + for draw_command in &self.draw_commands { + match &draw_command.primitive { + DrawPrimitive::Egui(_command) => {} + DrawPrimitive::PaintCallback(command) => { + let info = egui::PaintCallbackInfo { + viewport: command.rect, + clip_rect: draw_command.clip_rect, + pixels_per_point: self.pixels_per_point, + screen_size_px: [physical_width, physical_height], + }; + + command.callback.cb().prepare_render( + info, + render_context, + self.window_entity, + key, + world, + ); + } + } + } + let bind_groups = &world.get_resource::().unwrap(); let egui_transforms = world.get_resource::().unwrap(); @@ -434,18 +468,6 @@ impl Node for EguiNode { }); let mut render_pass = TrackedRenderPass::new(device, render_pass); - let (physical_width, physical_height, pipeline_key) = match extracted_window { - Some(window) => ( - window.physical_width, - window.physical_height, - EguiPipelineKey::from_extracted_window(window), - ), - None => unreachable!(), - }; - let Some(key) = pipeline_key else { - return Ok(()); - }; - let pipeline_id = egui_pipelines.get(&self.window_entity).unwrap(); let Some(pipeline) = pipeline_cache.get_render_pipeline(*pipeline_id) else { return Ok(()); @@ -671,6 +693,23 @@ pub trait EguiBevyPaintCallbackImpl: Send + Sync { world: &mut World, ); + /// Paint callback call before render step + /// + /// + /// Can be used to implement custom render passes + /// or to submit command buffers for execution before egui render pass + fn prepare_render<'w>( + &self, + info: egui::PaintCallbackInfo, + render_context: &mut RenderContext<'w>, + window_entity: Entity, + pipeline_key: EguiPipelineKey, + world: &'w World, + ) { + let _ = (info, render_context, window_entity, pipeline_key, world); + // Do nothing by default + } + /// Paint callback render step /// /// Native wgpu RenderPass can be retrieved from [`TrackedRenderPass`] by calling From 659798bbb1189df9283140ae05c500352fa24c54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C4=93teris=20Pakalns?= Date: Wed, 28 Aug 2024 19:00:52 +0300 Subject: [PATCH 2/2] Call prepare_render paint callback function in egui render to texture node --- src/egui_render_to_texture_node.rs | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/egui_render_to_texture_node.rs b/src/egui_render_to_texture_node.rs index 594c1da6..aef3e06b 100644 --- a/src/egui_render_to_texture_node.rs +++ b/src/egui_render_to_texture_node.rs @@ -231,11 +231,11 @@ impl Node for EguiRenderToTextureNode { } } - fn run( + fn run<'w>( &self, _graph: &mut RenderGraphContext, - render_context: &mut RenderContext, - world: &World, + render_context: &mut RenderContext<'w>, + world: &'w World, ) -> Result<(), NodeRunError> { let egui_pipelines = &world.get_resource::().unwrap().0; let pipeline_cache = world.get_resource::().unwrap(); @@ -260,6 +260,28 @@ impl Node for EguiRenderToTextureNode { render_queue.write_buffer(vertex_buffer, 0, &self.vertex_data); render_queue.write_buffer(index_buffer, 0, &self.index_data); + for draw_command in &self.draw_commands { + match &draw_command.primitive { + DrawPrimitive::Egui(_command) => {} + DrawPrimitive::PaintCallback(command) => { + let info = egui::PaintCallbackInfo { + viewport: command.rect, + clip_rect: draw_command.clip_rect, + pixels_per_point: self.pixels_per_point, + screen_size_px: [gpu_image.size.x, gpu_image.size.y], + }; + + command.callback.cb().prepare_render( + info, + render_context, + self.render_to_texture_target, + key, + world, + ); + } + } + } + let bind_groups = &world.get_resource::().unwrap(); let egui_transforms = world.get_resource::().unwrap();