Allow to reuse the same RenderPass for multiple RenderPhases (#7043)
# Objective - The recently merged PR #7013 does not allow multiple `RenderPhase`s to share the same `RenderPass`. - Due to the introduced overhead we want to minimize the number of `RenderPass`es recorded during each frame. ## Solution - Take a constructed `TrackedRenderPass` instead of a `RenderPassDiscriptor` as a parameter to the `RenderPhase::render` method. --- ## Changelog To enable multiple `RenderPhases` to share the same `TrackedRenderPass`, the `RenderPhase::render` signature has changed. ```rust pub fn render<'w>( &self, render_pass: &mut TrackedRenderPass<'w>, world: &'w World, view: Entity) ``` Co-authored-by: Kurt Kühnert <51823519+kurtkuehnert@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									a5b1c46d5b
								
							
						
					
					
						commit
						b833bdab17
					
				@ -3,6 +3,7 @@ use crate::{
 | 
			
		||||
    core_2d::{camera_2d::Camera2d, Transparent2d},
 | 
			
		||||
};
 | 
			
		||||
use bevy_ecs::prelude::*;
 | 
			
		||||
use bevy_render::render_phase::TrackedRenderPass;
 | 
			
		||||
use bevy_render::{
 | 
			
		||||
    camera::ExtractedCamera,
 | 
			
		||||
    render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
 | 
			
		||||
@ -77,13 +78,16 @@ impl Node for MainPass2dNode {
 | 
			
		||||
                depth_stencil_attachment: None,
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            transparent_phase.render(
 | 
			
		||||
                world,
 | 
			
		||||
                render_context,
 | 
			
		||||
                view_entity,
 | 
			
		||||
                camera.viewport.as_ref(),
 | 
			
		||||
                pass_descriptor,
 | 
			
		||||
            );
 | 
			
		||||
            let render_pass = render_context
 | 
			
		||||
                .command_encoder
 | 
			
		||||
                .begin_render_pass(&pass_descriptor);
 | 
			
		||||
            let mut render_pass = TrackedRenderPass::new(render_pass);
 | 
			
		||||
 | 
			
		||||
            if let Some(viewport) = camera.viewport.as_ref() {
 | 
			
		||||
                render_pass.set_camera_viewport(viewport);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            transparent_phase.render(&mut render_pass, world, view_entity);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // WebGL2 quirk: if ending with a render pass with a custom viewport, the viewport isn't
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,7 @@ use crate::{
 | 
			
		||||
    core_3d::{AlphaMask3d, Camera3d, Opaque3d, Transparent3d},
 | 
			
		||||
};
 | 
			
		||||
use bevy_ecs::prelude::*;
 | 
			
		||||
use bevy_render::render_phase::TrackedRenderPass;
 | 
			
		||||
use bevy_render::{
 | 
			
		||||
    camera::ExtractedCamera,
 | 
			
		||||
    render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
 | 
			
		||||
@ -95,13 +96,16 @@ impl Node for MainPass3dNode {
 | 
			
		||||
                }),
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            opaque_phase.render(
 | 
			
		||||
                world,
 | 
			
		||||
                render_context,
 | 
			
		||||
                view_entity,
 | 
			
		||||
                camera.viewport.as_ref(),
 | 
			
		||||
                pass_descriptor,
 | 
			
		||||
            );
 | 
			
		||||
            let render_pass = render_context
 | 
			
		||||
                .command_encoder
 | 
			
		||||
                .begin_render_pass(&pass_descriptor);
 | 
			
		||||
            let mut render_pass = TrackedRenderPass::new(render_pass);
 | 
			
		||||
 | 
			
		||||
            if let Some(viewport) = camera.viewport.as_ref() {
 | 
			
		||||
                render_pass.set_camera_viewport(viewport);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            opaque_phase.render(&mut render_pass, world, view_entity);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if !alpha_mask_phase.items.is_empty() {
 | 
			
		||||
@ -127,13 +131,16 @@ impl Node for MainPass3dNode {
 | 
			
		||||
                }),
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            alpha_mask_phase.render(
 | 
			
		||||
                world,
 | 
			
		||||
                render_context,
 | 
			
		||||
                view_entity,
 | 
			
		||||
                camera.viewport.as_ref(),
 | 
			
		||||
                pass_descriptor,
 | 
			
		||||
            );
 | 
			
		||||
            let render_pass = render_context
 | 
			
		||||
                .command_encoder
 | 
			
		||||
                .begin_render_pass(&pass_descriptor);
 | 
			
		||||
            let mut render_pass = TrackedRenderPass::new(render_pass);
 | 
			
		||||
 | 
			
		||||
            if let Some(viewport) = camera.viewport.as_ref() {
 | 
			
		||||
                render_pass.set_camera_viewport(viewport);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            alpha_mask_phase.render(&mut render_pass, world, view_entity);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if !transparent_phase.items.is_empty() {
 | 
			
		||||
@ -164,13 +171,16 @@ impl Node for MainPass3dNode {
 | 
			
		||||
                }),
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            transparent_phase.render(
 | 
			
		||||
                world,
 | 
			
		||||
                render_context,
 | 
			
		||||
                view_entity,
 | 
			
		||||
                camera.viewport.as_ref(),
 | 
			
		||||
                pass_descriptor,
 | 
			
		||||
            );
 | 
			
		||||
            let render_pass = render_context
 | 
			
		||||
                .command_encoder
 | 
			
		||||
                .begin_render_pass(&pass_descriptor);
 | 
			
		||||
            let mut render_pass = TrackedRenderPass::new(render_pass);
 | 
			
		||||
 | 
			
		||||
            if let Some(viewport) = camera.viewport.as_ref() {
 | 
			
		||||
                render_pass.set_camera_viewport(viewport);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            transparent_phase.render(&mut render_pass, world, view_entity);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // WebGL2 quirk: if ending with a render pass with a custom viewport, the viewport isn't
 | 
			
		||||
 | 
			
		||||
@ -1785,13 +1785,12 @@ impl Node for ShadowPassNode {
 | 
			
		||||
                    }),
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                shadow_phase.render(
 | 
			
		||||
                    world,
 | 
			
		||||
                    render_context,
 | 
			
		||||
                    view_light_entity,
 | 
			
		||||
                    None,
 | 
			
		||||
                    pass_descriptor,
 | 
			
		||||
                );
 | 
			
		||||
                let render_pass = render_context
 | 
			
		||||
                    .command_encoder
 | 
			
		||||
                    .begin_render_pass(&pass_descriptor);
 | 
			
		||||
                let mut render_pass = TrackedRenderPass::new(render_pass);
 | 
			
		||||
 | 
			
		||||
                shadow_phase.render(&mut render_pass, world, view_light_entity);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,10 +4,7 @@ mod draw_state;
 | 
			
		||||
use bevy_ecs::entity::Entity;
 | 
			
		||||
pub use draw::*;
 | 
			
		||||
pub use draw_state::*;
 | 
			
		||||
use wgpu::RenderPassDescriptor;
 | 
			
		||||
 | 
			
		||||
use crate::camera::Viewport;
 | 
			
		||||
use crate::renderer::RenderContext;
 | 
			
		||||
use bevy_ecs::prelude::{Component, Query};
 | 
			
		||||
use bevy_ecs::world::World;
 | 
			
		||||
 | 
			
		||||
@ -35,29 +32,18 @@ impl<I: PhaseItem> RenderPhase<I> {
 | 
			
		||||
        I::sort(&mut self.items);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn render(
 | 
			
		||||
    pub fn render<'w>(
 | 
			
		||||
        &self,
 | 
			
		||||
        world: &World,
 | 
			
		||||
        render_context: &mut RenderContext,
 | 
			
		||||
        render_pass: &mut TrackedRenderPass<'w>,
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
        view: Entity,
 | 
			
		||||
        viewport: Option<&Viewport>,
 | 
			
		||||
        pass_descriptor: RenderPassDescriptor,
 | 
			
		||||
    ) {
 | 
			
		||||
        let render_pass = render_context
 | 
			
		||||
            .command_encoder
 | 
			
		||||
            .begin_render_pass(&pass_descriptor);
 | 
			
		||||
        let mut render_pass = TrackedRenderPass::new(render_pass);
 | 
			
		||||
 | 
			
		||||
        if let Some(viewport) = viewport {
 | 
			
		||||
            render_pass.set_camera_viewport(viewport);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let draw_functions = world.resource::<DrawFunctions<I>>();
 | 
			
		||||
        let mut draw_functions = draw_functions.write();
 | 
			
		||||
 | 
			
		||||
        for item in &self.items {
 | 
			
		||||
            let draw_function = draw_functions.get_mut(item.draw_function()).unwrap();
 | 
			
		||||
            draw_function.draw(world, &mut render_pass, view, item);
 | 
			
		||||
            draw_function.draw(world, render_pass, view, item);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -85,7 +85,13 @@ impl Node for UiPassNode {
 | 
			
		||||
            depth_stencil_attachment: None,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        transparent_phase.render(world, render_context, view_entity, None, pass_descriptor);
 | 
			
		||||
        let render_pass = render_context
 | 
			
		||||
            .command_encoder
 | 
			
		||||
            .begin_render_pass(&pass_descriptor);
 | 
			
		||||
        let mut render_pass = TrackedRenderPass::new(render_pass);
 | 
			
		||||
 | 
			
		||||
        transparent_phase.render(&mut render_pass, world, view_entity);
 | 
			
		||||
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user