Skip to content

Commit ff76186

Browse files
committed
bevy_core_pipeline: Merge main_pass_3d passes into one
They all use the same configuration so merging them gives better performance, particularly on mobile, as the attachments have to be written out and read in between passes.
1 parent 3d8d922 commit ff76186

File tree

1 file changed

+29
-75
lines changed

1 file changed

+29
-75
lines changed

crates/bevy_core_pipeline/src/main_pass_3d.rs

Lines changed: 29 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -48,44 +48,49 @@ impl Node for MainPass3dNode {
4848
render_context: &mut RenderContext,
4949
world: &World,
5050
) -> Result<(), NodeRunError> {
51+
#[cfg(feature = "trace")]
52+
let _main_pbr_pass_3d_span = info_span!("main_pbr_pass_3d").entered();
53+
5154
let view_entity = graph.get_input_entity(Self::IN_VIEW)?;
5255
let (opaque_phase, alpha_mask_phase, transparent_phase, target, depth) =
5356
match self.query.get_manual(world, view_entity) {
5457
Ok(query) => query,
5558
Err(_) => return Ok(()), // No window
5659
};
5760

61+
let pass_descriptor = RenderPassDescriptor {
62+
label: Some("main_pbr_pass_3d"),
63+
color_attachments: &[target.get_color_attachment(Operations {
64+
load: LoadOp::Load,
65+
store: true,
66+
})],
67+
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
68+
view: &depth.view,
69+
// NOTE: For the transparent pass, there should be no need to write to the depth
70+
// buffer, but store is set to `true` as a workaround for issue #3776,
71+
// https://github.com/bevyengine/bevy/issues/3776
72+
// so that wgpu does not clear the depth buffer.
73+
// As the opaque and alpha mask passes run first, opaque meshes can occlude
74+
// transparent ones.
75+
depth_ops: Some(Operations {
76+
load: LoadOp::Load,
77+
store: true,
78+
}),
79+
stencil_ops: None,
80+
}),
81+
};
82+
let render_pass = render_context
83+
.command_encoder
84+
.begin_render_pass(&pass_descriptor);
85+
let mut tracked_pass = TrackedRenderPass::new(render_pass);
86+
5887
if !opaque_phase.items.is_empty() {
5988
// Run the opaque pass, sorted front-to-back
60-
// NOTE: Scoped to drop the mutable borrow of render_context
6189
#[cfg(feature = "trace")]
6290
let _main_opaque_pass_3d_span = info_span!("main_opaque_pass_3d").entered();
63-
let pass_descriptor = RenderPassDescriptor {
64-
label: Some("main_opaque_pass_3d"),
65-
// NOTE: The opaque pass loads the color
66-
// buffer as well as writing to it.
67-
color_attachments: &[target.get_color_attachment(Operations {
68-
load: LoadOp::Load,
69-
store: true,
70-
})],
71-
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
72-
view: &depth.view,
73-
// NOTE: The opaque main pass loads the depth buffer and possibly overwrites it
74-
depth_ops: Some(Operations {
75-
load: LoadOp::Load,
76-
store: true,
77-
}),
78-
stencil_ops: None,
79-
}),
80-
};
8191

8292
let draw_functions = world.resource::<DrawFunctions<Opaque3d>>();
83-
84-
let render_pass = render_context
85-
.command_encoder
86-
.begin_render_pass(&pass_descriptor);
8793
let mut draw_functions = draw_functions.write();
88-
let mut tracked_pass = TrackedRenderPass::new(render_pass);
8994
for item in &opaque_phase.items {
9095
let draw_function = draw_functions.get_mut(item.draw_function).unwrap();
9196
draw_function.draw(world, &mut tracked_pass, view_entity, item);
@@ -94,34 +99,11 @@ impl Node for MainPass3dNode {
9499

95100
if !alpha_mask_phase.items.is_empty() {
96101
// Run the alpha mask pass, sorted front-to-back
97-
// NOTE: Scoped to drop the mutable borrow of render_context
98102
#[cfg(feature = "trace")]
99103
let _main_alpha_mask_pass_3d_span = info_span!("main_alpha_mask_pass_3d").entered();
100-
let pass_descriptor = RenderPassDescriptor {
101-
label: Some("main_alpha_mask_pass_3d"),
102-
// NOTE: The alpha_mask pass loads the color buffer as well as overwriting it where appropriate.
103-
color_attachments: &[target.get_color_attachment(Operations {
104-
load: LoadOp::Load,
105-
store: true,
106-
})],
107-
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
108-
view: &depth.view,
109-
// NOTE: The alpha mask pass loads the depth buffer and possibly overwrites it
110-
depth_ops: Some(Operations {
111-
load: LoadOp::Load,
112-
store: true,
113-
}),
114-
stencil_ops: None,
115-
}),
116-
};
117104

118105
let draw_functions = world.resource::<DrawFunctions<AlphaMask3d>>();
119-
120-
let render_pass = render_context
121-
.command_encoder
122-
.begin_render_pass(&pass_descriptor);
123106
let mut draw_functions = draw_functions.write();
124-
let mut tracked_pass = TrackedRenderPass::new(render_pass);
125107
for item in &alpha_mask_phase.items {
126108
let draw_function = draw_functions.get_mut(item.draw_function).unwrap();
127109
draw_function.draw(world, &mut tracked_pass, view_entity, item);
@@ -130,39 +112,11 @@ impl Node for MainPass3dNode {
130112

131113
if !transparent_phase.items.is_empty() {
132114
// Run the transparent pass, sorted back-to-front
133-
// NOTE: Scoped to drop the mutable borrow of render_context
134115
#[cfg(feature = "trace")]
135116
let _main_transparent_pass_3d_span = info_span!("main_transparent_pass_3d").entered();
136-
let pass_descriptor = RenderPassDescriptor {
137-
label: Some("main_transparent_pass_3d"),
138-
// NOTE: The transparent pass loads the color buffer as well as overwriting it where appropriate.
139-
color_attachments: &[target.get_color_attachment(Operations {
140-
load: LoadOp::Load,
141-
store: true,
142-
})],
143-
depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {
144-
view: &depth.view,
145-
// NOTE: For the transparent pass we load the depth buffer. There should be no
146-
// need to write to it, but store is set to `true` as a workaround for issue #3776,
147-
// https://github.com/bevyengine/bevy/issues/3776
148-
// so that wgpu does not clear the depth buffer.
149-
// As the opaque and alpha mask passes run first, opaque meshes can occlude
150-
// transparent ones.
151-
depth_ops: Some(Operations {
152-
load: LoadOp::Load,
153-
store: true,
154-
}),
155-
stencil_ops: None,
156-
}),
157-
};
158117

159118
let draw_functions = world.resource::<DrawFunctions<Transparent3d>>();
160-
161-
let render_pass = render_context
162-
.command_encoder
163-
.begin_render_pass(&pass_descriptor);
164119
let mut draw_functions = draw_functions.write();
165-
let mut tracked_pass = TrackedRenderPass::new(render_pass);
166120
for item in &transparent_phase.items {
167121
let draw_function = draw_functions.get_mut(item.draw_function).unwrap();
168122
draw_function.draw(world, &mut tracked_pass, view_entity, item);

0 commit comments

Comments
 (0)