Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Queue Phase parallelization and other small optimizations #4899

Closed
wants to merge 12 commits into from
4 changes: 2 additions & 2 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 @@ -108,7 +108,7 @@ impl Node for MainPass3dNode {
opaque_phase.render(&mut render_pass, world, view_entity);
}

if !alpha_mask_phase.items.is_empty() {
if !alpha_mask_phase.sorted.is_empty() {
// Run the alpha mask pass, sorted front-to-back
// NOTE: Scoped to drop the mutable borrow of render_context
#[cfg(feature = "trace")]
Expand Down Expand Up @@ -143,7 +143,7 @@ impl Node for MainPass3dNode {
alpha_mask_phase.render(&mut render_pass, world, view_entity);
}

if !transparent_phase.items.is_empty() {
if !transparent_phase.sorted.is_empty() {
// Run the transparent pass, sorted back-to-front
// NOTE: Scoped to drop the mutable borrow of render_context
#[cfg(feature = "trace")]
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_core_pipeline/src/fxaa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ impl SpecializedRenderPipeline for FxaaPipeline {

pub fn prepare_fxaa_pipelines(
mut commands: Commands,
mut pipeline_cache: ResMut<PipelineCache>,
pipeline_cache: Res<LockablePipelineCache>,
mut pipelines: ResMut<SpecializedRenderPipelines<FxaaPipeline>>,
fxaa_pipeline: Res<FxaaPipeline>,
views: Query<(Entity, &ExtractedView, &Fxaa)>,
Expand All @@ -232,7 +232,7 @@ pub fn prepare_fxaa_pipelines(
continue;
}
let pipeline_id = pipelines.specialize(
&mut pipeline_cache,
&pipeline_cache,
&fxaa_pipeline,
FxaaPipelineKey {
edge_threshold: fxaa.edge_threshold,
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_core_pipeline/src/tonemapping/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ pub struct ViewTonemappingPipeline(CachedRenderPipelineId);

pub fn queue_view_tonemapping_pipelines(
mut commands: Commands,
mut pipeline_cache: ResMut<PipelineCache>,
pipeline_cache: Res<LockablePipelineCache>,
mut pipelines: ResMut<SpecializedRenderPipelines<TonemappingPipeline>>,
upscaling_pipeline: Res<TonemappingPipeline>,
view_targets: Query<(Entity, &Tonemapping)>,
Expand All @@ -136,7 +136,7 @@ pub fn queue_view_tonemapping_pipelines(
let key = TonemappingPipelineKey {
deband_dither: *deband_dither,
};
let pipeline = pipelines.specialize(&mut pipeline_cache, &upscaling_pipeline, key);
let pipeline = pipelines.specialize(&pipeline_cache, &upscaling_pipeline, key);

commands
.entity(entity)
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_core_pipeline/src/upscaling/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ pub struct ViewUpscalingPipeline(CachedRenderPipelineId);

fn queue_view_upscaling_pipelines(
mut commands: Commands,
mut pipeline_cache: ResMut<PipelineCache>,
pipeline_cache: Res<LockablePipelineCache>,
mut pipelines: ResMut<SpecializedRenderPipelines<UpscalingPipeline>>,
upscaling_pipeline: Res<UpscalingPipeline>,
view_targets: Query<(Entity, &ViewTarget)>,
Expand All @@ -122,7 +122,7 @@ fn queue_view_upscaling_pipelines(
upscaling_mode: UpscalingMode::Filtering,
texture_format: view_target.out_texture_format(),
};
let pipeline = pipelines.specialize(&mut pipeline_cache, &upscaling_pipeline, key);
let pipeline = pipelines.specialize(&pipeline_cache, &upscaling_pipeline, key);

commands
.entity(entity)
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_pbr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ bevy_derive = { path = "../bevy_derive", version = "0.9.0" }
bitflags = "1.2"
# direct dependency required for derive macro
bytemuck = { version = "1", features = ["derive"] }
copyless = "0.1"
radsort = "0.1"
44 changes: 25 additions & 19 deletions crates/bevy_pbr/src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ use bevy_render::{
RenderPhase, SetItemPipeline, TrackedRenderPass,
},
render_resource::{
AsBindGroup, AsBindGroupError, BindGroup, BindGroupLayout, OwnedBindingResource,
PipelineCache, RenderPipelineDescriptor, Shader, ShaderRef, SpecializedMeshPipeline,
AsBindGroup, AsBindGroupError, BindGroup, BindGroupLayout, LockablePipelineCache,
OwnedBindingResource, RenderPipelineDescriptor, Shader, ShaderRef, SpecializedMeshPipeline,
SpecializedMeshPipelineError, SpecializedMeshPipelines,
},
renderer::RenderDevice,
Expand Down Expand Up @@ -321,30 +321,24 @@ pub fn queue_material_meshes<M: Material>(
transparent_draw_functions: Res<DrawFunctions<Transparent3d>>,
material_pipeline: Res<MaterialPipeline<M>>,
mut pipelines: ResMut<SpecializedMeshPipelines<MaterialPipeline<M>>>,
mut pipeline_cache: ResMut<PipelineCache>,
pipeline_cache: Res<LockablePipelineCache>,
msaa: Res<Msaa>,
render_meshes: Res<RenderAssets<Mesh>>,
render_materials: Res<RenderMaterials<M>>,
material_meshes: Query<(&Handle<M>, &Handle<Mesh>, &MeshUniform)>,
mut views: Query<(
views: Query<(
&ExtractedView,
&VisibleEntities,
Option<&Tonemapping>,
&mut RenderPhase<Opaque3d>,
&mut RenderPhase<AlphaMask3d>,
&mut RenderPhase<Transparent3d>,
&RenderPhase<Opaque3d>,
&RenderPhase<AlphaMask3d>,
&RenderPhase<Transparent3d>,
)>,
) where
M::Data: PartialEq + Eq + Hash + Clone,
{
for (
view,
visible_entities,
tonemapping,
mut opaque_phase,
mut alpha_mask_phase,
mut transparent_phase,
) in &mut views
for (view, visible_entities, tonemapping, opaque_phase, alpha_mask_phase, transparent_phase) in
&views
{
let draw_opaque_pbr = opaque_draw_functions.read().id::<DrawMaterial<M>>();
let draw_alpha_mask_pbr = alpha_mask_draw_functions.read().id::<DrawMaterial<M>>();
Expand All @@ -364,6 +358,14 @@ pub fn queue_material_meshes<M: Material>(
}
let rangefinder = view.rangefinder3d();

let opaque_phase_cell = opaque_phase.get();
let alpha_mask_phase_cell = alpha_mask_phase.get();
let transparent_phase_cell = transparent_phase.get();

let mut opaque_phase_queue = opaque_phase_cell.take();
let mut alpha_mask_phase_queue = alpha_mask_phase_cell.take();
let mut transparent_phase_queue = transparent_phase_cell.take();

for visible_entity in &visible_entities.entities {
if let Ok((material_handle, mesh_handle, mesh_uniform)) =
material_meshes.get(*visible_entity)
Expand All @@ -379,7 +381,7 @@ pub fn queue_material_meshes<M: Material>(
}

let pipeline_id = pipelines.specialize(
&mut pipeline_cache,
&pipeline_cache,
&material_pipeline,
MaterialPipelineKey {
mesh_key,
Expand All @@ -399,23 +401,23 @@ pub fn queue_material_meshes<M: Material>(
+ material.properties.depth_bias;
match alpha_mode {
AlphaMode::Opaque => {
opaque_phase.add(Opaque3d {
opaque_phase_queue.push(Opaque3d {
entity: *visible_entity,
draw_function: draw_opaque_pbr,
pipeline: pipeline_id,
distance,
});
}
AlphaMode::Mask(_) => {
alpha_mask_phase.add(AlphaMask3d {
alpha_mask_phase_queue.push(AlphaMask3d {
entity: *visible_entity,
draw_function: draw_alpha_mask_pbr,
pipeline: pipeline_id,
distance,
});
}
AlphaMode::Blend => {
transparent_phase.add(Transparent3d {
transparent_phase_queue.push(Transparent3d {
entity: *visible_entity,
draw_function: draw_transparent_pbr,
pipeline: pipeline_id,
Expand All @@ -427,6 +429,10 @@ pub fn queue_material_meshes<M: Material>(
}
}
}

opaque_phase_cell.set(opaque_phase_queue);
alpha_mask_phase_cell.set(alpha_mask_phase_queue);
transparent_phase_cell.set(transparent_phase_queue);
}
}

Expand Down
70 changes: 36 additions & 34 deletions crates/bevy_pbr/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1626,18 +1626,18 @@ pub fn queue_shadows(
casting_meshes: Query<&Handle<Mesh>, Without<NotShadowCaster>>,
render_meshes: Res<RenderAssets<Mesh>>,
mut pipelines: ResMut<SpecializedMeshPipelines<ShadowPipeline>>,
mut pipeline_cache: ResMut<PipelineCache>,
pipeline_cache: Res<LockablePipelineCache>,
view_lights: Query<&ViewLightEntities>,
mut view_light_shadow_phases: Query<(&LightEntity, &mut RenderPhase<Shadow>)>,
view_light_shadow_phases: Query<(&LightEntity, &RenderPhase<Shadow>)>,
point_light_entities: Query<&CubemapVisibleEntities, With<ExtractedPointLight>>,
directional_light_entities: Query<&VisibleEntities, With<ExtractedDirectionalLight>>,
spot_light_entities: Query<&VisibleEntities, With<ExtractedPointLight>>,
) {
for view_lights in &view_lights {
let draw_shadow_mesh = shadow_draw_functions.read().id::<DrawShadowMesh>();
for view_light_entity in view_lights.lights.iter().copied() {
let (light_entity, mut shadow_phase) =
view_light_shadow_phases.get_mut(view_light_entity).unwrap();
let (light_entity, shadow_phase) =
view_light_shadow_phases.get(view_light_entity).unwrap();
let visible_entities = match light_entity {
LightEntity::Directional { light_entity } => directional_light_entities
.get(*light_entity)
Expand All @@ -1653,37 +1653,39 @@ pub fn queue_shadows(
.get(*light_entity)
.expect("Failed to get spot light visible entities"),
};
// NOTE: Lights with shadow mapping disabled will have no visible entities
// so no meshes will be queued
for entity in visible_entities.iter().copied() {
if let Ok(mesh_handle) = casting_meshes.get(entity) {
if let Some(mesh) = render_meshes.get(mesh_handle) {
let key =
ShadowPipelineKey::from_primitive_topology(mesh.primitive_topology);
let pipeline_id = pipelines.specialize(
&mut pipeline_cache,
&shadow_pipeline,
key,
&mesh.layout,
);

let pipeline_id = match pipeline_id {
Ok(id) => id,
Err(err) => {
error!("{}", err);
continue;
}
};

shadow_phase.add(Shadow {
draw_function: draw_shadow_mesh,
pipeline: pipeline_id,
entity,
distance: 0.0, // TODO: sort back-to-front
});
shadow_phase.phase_scope(|mut phase| {
// NOTE: Lights with shadow mapping disabled will have no visible entities
// so no meshes will be queued
for entity in visible_entities.iter().copied() {
if let Ok(mesh_handle) = casting_meshes.get(entity) {
if let Some(mesh) = render_meshes.get(mesh_handle) {
let key =
ShadowPipelineKey::from_primitive_topology(mesh.primitive_topology);
let pipeline_id = pipelines.specialize(
&pipeline_cache,
&shadow_pipeline,
key,
&mesh.layout,
);

let pipeline_id = match pipeline_id {
Ok(id) => id,
Err(err) => {
error!("{}", err);
continue;
}
};

phase.add(Shadow {
draw_function: draw_shadow_mesh,
pipeline: pipeline_id,
entity,
distance: 0.0, // TODO: sort back-to-front
});
}
}
}
}
});
}
}
}
Expand Down Expand Up @@ -1766,7 +1768,7 @@ impl Node for ShadowPassNode {
.get_manual(world, view_light_entity)
.unwrap();

if shadow_phase.items.is_empty() {
if shadow_phase.sorted.is_empty() {
continue;
}

Expand Down
Loading