Skip to content

Commit 73dd7fc

Browse files
danchiaItsDoot
authored andcommitted
Make PipelineCache internally mutable. (bevyengine#7205)
# Objective - Allow rendering queue systems to use a `Res<PipelineCache>` even for queueing up new rendering pipelines. This is part of unblocking parallel execution queue systems. ## Solution - Make `PipelineCache` internally mutable w.r.t to queueing new pipelines. Pipelines are no longer immediately updated into the cache state, but rather queued into a Vec. The Vec of pending new pipelines is then later processed at the same time we actually create the queued pipelines on the GPU device. --- ## Changelog `PipelineCache` no longer requires mutable access in order to queue render / compute pipelines. ## Migration Guide * Most usages of `resource_mut::<PipelineCache>` and `ResMut<PipelineCache>` can be changed to `resource::<PipelineCache>` and `Res<PipelineCache>` as long as they don't use any methods requiring mutability - the only public method requiring it is `process_queue`.
1 parent 7848f4a commit 73dd7fc

File tree

16 files changed

+50
-36
lines changed

16 files changed

+50
-36
lines changed

crates/bevy_core_pipeline/src/bloom/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ impl FromWorld for BloomPipelines {
434434
],
435435
});
436436

437-
let mut pipeline_cache = world.resource_mut::<PipelineCache>();
437+
let pipeline_cache = world.resource::<PipelineCache>();
438438

439439
let downsampling_prefilter_pipeline =
440440
pipeline_cache.queue_render_pipeline(RenderPipelineDescriptor {

crates/bevy_core_pipeline/src/fxaa/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ impl SpecializedRenderPipeline for FxaaPipeline {
223223

224224
pub fn prepare_fxaa_pipelines(
225225
mut commands: Commands,
226-
mut pipeline_cache: ResMut<PipelineCache>,
226+
pipeline_cache: Res<PipelineCache>,
227227
mut pipelines: ResMut<SpecializedRenderPipelines<FxaaPipeline>>,
228228
fxaa_pipeline: Res<FxaaPipeline>,
229229
views: Query<(Entity, &ExtractedView, &Fxaa)>,
@@ -233,7 +233,7 @@ pub fn prepare_fxaa_pipelines(
233233
continue;
234234
}
235235
let pipeline_id = pipelines.specialize(
236-
&mut pipeline_cache,
236+
&pipeline_cache,
237237
&fxaa_pipeline,
238238
FxaaPipelineKey {
239239
edge_threshold: fxaa.edge_threshold,

crates/bevy_core_pipeline/src/tonemapping/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ pub struct ViewTonemappingPipeline(CachedRenderPipelineId);
126126

127127
pub fn queue_view_tonemapping_pipelines(
128128
mut commands: Commands,
129-
mut pipeline_cache: ResMut<PipelineCache>,
129+
pipeline_cache: Res<PipelineCache>,
130130
mut pipelines: ResMut<SpecializedRenderPipelines<TonemappingPipeline>>,
131131
upscaling_pipeline: Res<TonemappingPipeline>,
132132
view_targets: Query<(Entity, &Tonemapping)>,
@@ -136,7 +136,7 @@ pub fn queue_view_tonemapping_pipelines(
136136
let key = TonemappingPipelineKey {
137137
deband_dither: *deband_dither,
138138
};
139-
let pipeline = pipelines.specialize(&mut pipeline_cache, &upscaling_pipeline, key);
139+
let pipeline = pipelines.specialize(&pipeline_cache, &upscaling_pipeline, key);
140140

141141
commands
142142
.entity(entity)

crates/bevy_core_pipeline/src/upscaling/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ pub struct ViewUpscalingPipeline(CachedRenderPipelineId);
112112

113113
fn queue_view_upscaling_pipelines(
114114
mut commands: Commands,
115-
mut pipeline_cache: ResMut<PipelineCache>,
115+
pipeline_cache: Res<PipelineCache>,
116116
mut pipelines: ResMut<SpecializedRenderPipelines<UpscalingPipeline>>,
117117
upscaling_pipeline: Res<UpscalingPipeline>,
118118
view_targets: Query<(Entity, &ViewTarget)>,
@@ -122,7 +122,7 @@ fn queue_view_upscaling_pipelines(
122122
upscaling_mode: UpscalingMode::Filtering,
123123
texture_format: view_target.out_texture_format(),
124124
};
125-
let pipeline = pipelines.specialize(&mut pipeline_cache, &upscaling_pipeline, key);
125+
let pipeline = pipelines.specialize(&pipeline_cache, &upscaling_pipeline, key);
126126

127127
commands
128128
.entity(entity)

crates/bevy_pbr/src/material.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ pub fn queue_material_meshes<M: Material>(
333333
transparent_draw_functions: Res<DrawFunctions<Transparent3d>>,
334334
material_pipeline: Res<MaterialPipeline<M>>,
335335
mut pipelines: ResMut<SpecializedMeshPipelines<MaterialPipeline<M>>>,
336-
mut pipeline_cache: ResMut<PipelineCache>,
336+
pipeline_cache: Res<PipelineCache>,
337337
msaa: Res<Msaa>,
338338
render_meshes: Res<RenderAssets<Mesh>>,
339339
render_materials: Res<RenderMaterials<M>>,
@@ -391,7 +391,7 @@ pub fn queue_material_meshes<M: Material>(
391391
}
392392

393393
let pipeline_id = pipelines.specialize(
394-
&mut pipeline_cache,
394+
&pipeline_cache,
395395
&material_pipeline,
396396
MaterialPipelineKey {
397397
mesh_key,

crates/bevy_pbr/src/render/light.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,7 +1626,7 @@ pub fn queue_shadows(
16261626
casting_meshes: Query<&Handle<Mesh>, Without<NotShadowCaster>>,
16271627
render_meshes: Res<RenderAssets<Mesh>>,
16281628
mut pipelines: ResMut<SpecializedMeshPipelines<ShadowPipeline>>,
1629-
mut pipeline_cache: ResMut<PipelineCache>,
1629+
pipeline_cache: Res<PipelineCache>,
16301630
view_lights: Query<&ViewLightEntities>,
16311631
mut view_light_shadow_phases: Query<(&LightEntity, &mut RenderPhase<Shadow>)>,
16321632
point_light_entities: Query<&CubemapVisibleEntities, With<ExtractedPointLight>>,
@@ -1661,7 +1661,7 @@ pub fn queue_shadows(
16611661
let key =
16621662
ShadowPipelineKey::from_primitive_topology(mesh.primitive_topology);
16631663
let pipeline_id = pipelines.specialize(
1664-
&mut pipeline_cache,
1664+
&pipeline_cache,
16651665
&shadow_pipeline,
16661666
key,
16671667
&mesh.layout,

crates/bevy_pbr/src/wireframe.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ fn queue_wireframes(
108108
wireframe_config: Res<WireframeConfig>,
109109
wireframe_pipeline: Res<WireframePipeline>,
110110
mut pipelines: ResMut<SpecializedMeshPipelines<WireframePipeline>>,
111-
mut pipeline_cache: ResMut<PipelineCache>,
111+
pipeline_cache: Res<PipelineCache>,
112112
msaa: Res<Msaa>,
113113
mut material_meshes: ParamSet<(
114114
Query<(Entity, &Handle<Mesh>, &MeshUniform)>,
@@ -128,7 +128,7 @@ fn queue_wireframes(
128128
let key = view_key
129129
| MeshPipelineKey::from_primitive_topology(mesh.primitive_topology);
130130
let pipeline_id = pipelines.specialize(
131-
&mut pipeline_cache,
131+
&pipeline_cache,
132132
&wireframe_pipeline,
133133
key,
134134
&mesh.layout,

crates/bevy_render/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ impl Plugin for RenderPlugin {
198198
.add_stage(
199199
RenderStage::Render,
200200
SystemStage::parallel()
201+
// Note: Must run before `render_system` in order to
202+
// processed newly queued pipelines.
201203
.with_system(PipelineCache::process_pipeline_queue_system)
202204
.with_system(render_system.at_end()),
203205
)

crates/bevy_render/src/render_resource/pipeline_cache.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use bevy_utils::{
1717
tracing::{debug, error},
1818
Entry, HashMap, HashSet,
1919
};
20+
use parking_lot::Mutex;
2021
use std::{hash::Hash, iter::FusedIterator, mem, ops::Deref};
2122
use thiserror::Error;
2223
use wgpu::{PipelineLayoutDescriptor, VertexBufferLayout as RawVertexBufferLayout};
@@ -343,6 +344,7 @@ pub struct PipelineCache {
343344
device: RenderDevice,
344345
pipelines: Vec<CachedPipeline>,
345346
waiting_pipelines: HashSet<CachedPipelineId>,
347+
new_pipelines: Mutex<Vec<CachedPipeline>>,
346348
}
347349

348350
impl PipelineCache {
@@ -357,6 +359,7 @@ impl PipelineCache {
357359
layout_cache: default(),
358360
shader_cache: default(),
359361
waiting_pipelines: default(),
362+
new_pipelines: default(),
360363
pipelines: default(),
361364
}
362365
}
@@ -455,15 +458,15 @@ impl PipelineCache {
455458
/// [`get_render_pipeline_state()`]: PipelineCache::get_render_pipeline_state
456459
/// [`get_render_pipeline()`]: PipelineCache::get_render_pipeline
457460
pub fn queue_render_pipeline(
458-
&mut self,
461+
&self,
459462
descriptor: RenderPipelineDescriptor,
460463
) -> CachedRenderPipelineId {
461-
let id = CachedRenderPipelineId(self.pipelines.len());
462-
self.pipelines.push(CachedPipeline {
464+
let mut new_pipelines = self.new_pipelines.lock();
465+
let id = CachedRenderPipelineId(self.pipelines.len() + new_pipelines.len());
466+
new_pipelines.push(CachedPipeline {
463467
descriptor: PipelineDescriptor::RenderPipelineDescriptor(Box::new(descriptor)),
464468
state: CachedPipelineState::Queued,
465469
});
466-
self.waiting_pipelines.insert(id.0);
467470
id
468471
}
469472

@@ -481,15 +484,15 @@ impl PipelineCache {
481484
/// [`get_compute_pipeline_state()`]: PipelineCache::get_compute_pipeline_state
482485
/// [`get_compute_pipeline()`]: PipelineCache::get_compute_pipeline
483486
pub fn queue_compute_pipeline(
484-
&mut self,
487+
&self,
485488
descriptor: ComputePipelineDescriptor,
486489
) -> CachedComputePipelineId {
487-
let id = CachedComputePipelineId(self.pipelines.len());
488-
self.pipelines.push(CachedPipeline {
490+
let mut new_pipelines = self.new_pipelines.lock();
491+
let id = CachedComputePipelineId(self.pipelines.len() + new_pipelines.len());
492+
new_pipelines.push(CachedPipeline {
489493
descriptor: PipelineDescriptor::ComputePipelineDescriptor(Box::new(descriptor)),
490494
state: CachedPipelineState::Queued,
491495
});
492-
self.waiting_pipelines.insert(id.0);
493496
id
494497
}
495498

@@ -632,9 +635,18 @@ impl PipelineCache {
632635
///
633636
/// [`RenderStage::Render`]: crate::RenderStage::Render
634637
pub fn process_queue(&mut self) {
635-
let waiting_pipelines = mem::take(&mut self.waiting_pipelines);
638+
let mut waiting_pipelines = mem::take(&mut self.waiting_pipelines);
636639
let mut pipelines = mem::take(&mut self.pipelines);
637640

641+
{
642+
let mut new_pipelines = self.new_pipelines.lock();
643+
for new_pipeline in new_pipelines.drain(..) {
644+
let id = pipelines.len();
645+
pipelines.push(new_pipeline);
646+
waiting_pipelines.insert(id);
647+
}
648+
}
649+
638650
for id in waiting_pipelines {
639651
let pipeline = &mut pipelines[id];
640652
if matches!(pipeline.state, CachedPipelineState::Ok(_)) {

crates/bevy_render/src/render_resource/pipeline_specializer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl<S: SpecializedRenderPipeline> Default for SpecializedRenderPipelines<S> {
3333
impl<S: SpecializedRenderPipeline> SpecializedRenderPipelines<S> {
3434
pub fn specialize(
3535
&mut self,
36-
cache: &mut PipelineCache,
36+
cache: &PipelineCache,
3737
specialize_pipeline: &S,
3838
key: S::Key,
3939
) -> CachedRenderPipelineId {
@@ -103,7 +103,7 @@ impl<S: SpecializedMeshPipeline> SpecializedMeshPipelines<S> {
103103
#[inline]
104104
pub fn specialize(
105105
&mut self,
106-
cache: &mut PipelineCache,
106+
cache: &PipelineCache,
107107
specialize_pipeline: &S,
108108
key: S::Key,
109109
layout: &MeshVertexBufferLayout,

crates/bevy_sprite/src/mesh2d/material.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ pub fn queue_material2d_meshes<M: Material2d>(
319319
transparent_draw_functions: Res<DrawFunctions<Transparent2d>>,
320320
material2d_pipeline: Res<Material2dPipeline<M>>,
321321
mut pipelines: ResMut<SpecializedMeshPipelines<Material2dPipeline<M>>>,
322-
mut pipeline_cache: ResMut<PipelineCache>,
322+
pipeline_cache: Res<PipelineCache>,
323323
msaa: Res<Msaa>,
324324
render_meshes: Res<RenderAssets<Mesh>>,
325325
render_materials: Res<RenderMaterials2d<M>>,
@@ -363,7 +363,7 @@ pub fn queue_material2d_meshes<M: Material2d>(
363363
| Mesh2dPipelineKey::from_primitive_topology(mesh.primitive_topology);
364364

365365
let pipeline_id = pipelines.specialize(
366-
&mut pipeline_cache,
366+
&pipeline_cache,
367367
&material2d_pipeline,
368368
Material2dKey {
369369
mesh_key,

crates/bevy_sprite/src/render/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ pub fn queue_sprites(
451451
view_uniforms: Res<ViewUniforms>,
452452
sprite_pipeline: Res<SpritePipeline>,
453453
mut pipelines: ResMut<SpecializedRenderPipelines<SpritePipeline>>,
454-
mut pipeline_cache: ResMut<PipelineCache>,
454+
pipeline_cache: Res<PipelineCache>,
455455
mut image_bind_groups: ResMut<ImageBindGroups>,
456456
gpu_images: Res<RenderAssets<Image>>,
457457
msaa: Res<Msaa>,
@@ -528,12 +528,12 @@ pub fn queue_sprites(
528528
}
529529
}
530530
let pipeline = pipelines.specialize(
531-
&mut pipeline_cache,
531+
&pipeline_cache,
532532
&sprite_pipeline,
533533
view_key | SpritePipelineKey::from_colored(false),
534534
);
535535
let colored_pipeline = pipelines.specialize(
536-
&mut pipeline_cache,
536+
&pipeline_cache,
537537
&sprite_pipeline,
538538
view_key | SpritePipelineKey::from_colored(true),
539539
);

crates/bevy_ui/src/render/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ pub fn queue_uinodes(
557557
view_uniforms: Res<ViewUniforms>,
558558
ui_pipeline: Res<UiPipeline>,
559559
mut pipelines: ResMut<SpecializedRenderPipelines<UiPipeline>>,
560-
mut pipeline_cache: ResMut<PipelineCache>,
560+
pipeline_cache: Res<PipelineCache>,
561561
mut image_bind_groups: ResMut<UiImageBindGroups>,
562562
gpu_images: Res<RenderAssets<Image>>,
563563
ui_batches: Query<(Entity, &UiBatch)>,
@@ -586,7 +586,7 @@ pub fn queue_uinodes(
586586
let draw_ui_function = draw_functions.read().id::<DrawUi>();
587587
for (view, mut transparent_phase) in &mut views {
588588
let pipeline = pipelines.specialize(
589-
&mut pipeline_cache,
589+
&pipeline_cache,
590590
&ui_pipeline,
591591
UiPipelineKey { hdr: view.hdr },
592592
);

examples/2d/mesh2d_manual.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ pub fn queue_colored_mesh2d(
312312
transparent_draw_functions: Res<DrawFunctions<Transparent2d>>,
313313
colored_mesh2d_pipeline: Res<ColoredMesh2dPipeline>,
314314
mut pipelines: ResMut<SpecializedRenderPipelines<ColoredMesh2dPipeline>>,
315-
mut pipeline_cache: ResMut<PipelineCache>,
315+
pipeline_cache: Res<PipelineCache>,
316316
msaa: Res<Msaa>,
317317
render_meshes: Res<RenderAssets<Mesh>>,
318318
colored_mesh2d: Query<(&Mesh2dHandle, &Mesh2dUniform), With<ColoredMesh2d>>,
@@ -343,7 +343,7 @@ pub fn queue_colored_mesh2d(
343343
}
344344

345345
let pipeline_id =
346-
pipelines.specialize(&mut pipeline_cache, &colored_mesh2d_pipeline, mesh2d_key);
346+
pipelines.specialize(&pipeline_cache, &colored_mesh2d_pipeline, mesh2d_key);
347347

348348
let mesh_z = mesh2d_uniform.transform.w_axis.z;
349349
transparent_phase.add(Transparent2d {

examples/shader/compute_shader_game_of_life.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ impl FromWorld for GameOfLifePipeline {
137137
let shader = world
138138
.resource::<AssetServer>()
139139
.load("shaders/game_of_life.wgsl");
140-
let mut pipeline_cache = world.resource_mut::<PipelineCache>();
140+
let pipeline_cache = world.resource::<PipelineCache>();
141141
let init_pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {
142142
label: None,
143143
layout: Some(vec![texture_bind_group_layout.clone()]),

examples/shader/shader_instancing.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ fn queue_custom(
104104
custom_pipeline: Res<CustomPipeline>,
105105
msaa: Res<Msaa>,
106106
mut pipelines: ResMut<SpecializedMeshPipelines<CustomPipeline>>,
107-
mut pipeline_cache: ResMut<PipelineCache>,
107+
pipeline_cache: Res<PipelineCache>,
108108
meshes: Res<RenderAssets<Mesh>>,
109109
material_meshes: Query<(Entity, &MeshUniform, &Handle<Mesh>), With<InstanceMaterialData>>,
110110
mut views: Query<(&ExtractedView, &mut RenderPhase<Transparent3d>)>,
@@ -121,7 +121,7 @@ fn queue_custom(
121121
let key =
122122
view_key | MeshPipelineKey::from_primitive_topology(mesh.primitive_topology);
123123
let pipeline = pipelines
124-
.specialize(&mut pipeline_cache, &custom_pipeline, key, &mesh.layout)
124+
.specialize(&pipeline_cache, &custom_pipeline, key, &mesh.layout)
125125
.unwrap();
126126
transparent_phase.add(Transparent3d {
127127
entity,

0 commit comments

Comments
 (0)