Skip to content

Commit 517deda

Browse files
committed
Make PipelineCache internally mutable. (#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 4b326fb commit 517deda

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,

0 commit comments

Comments
 (0)