Skip to content

Commit

Permalink
Allow to reuse the same RenderPass for multiple RenderPhases (#7043)
Browse files Browse the repository at this point in the history
# 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>
  • Loading branch information
kurtkuehnert and kurtkuehnert committed Jan 2, 2023
1 parent a5b1c46 commit b833bda
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 54 deletions.
18 changes: 11 additions & 7 deletions crates/bevy_core_pipeline/src/core_2d/main_pass_2d_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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
Expand Down
52 changes: 31 additions & 21 deletions crates/bevy_core_pipeline/src/core_3d/main_pass_3d_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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() {
Expand All @@ -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() {
Expand Down Expand Up @@ -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
Expand Down
13 changes: 6 additions & 7 deletions crates/bevy_pbr/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
22 changes: 4 additions & 18 deletions crates/bevy_render/src/render_phase/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion crates/bevy_ui/src/render/render_pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}
}
Expand Down

0 comments on commit b833bda

Please sign in to comment.