Skip to content

Commit 9fc412e

Browse files
committed
Optimize ShaderDefs updates
- change ShaderDefIterator to iterate every ShaderDef defined or not - remove clear system, and only update on change
1 parent 9239621 commit 9fc412e

File tree

3 files changed

+31
-46
lines changed

3 files changed

+31
-46
lines changed

crates/bevy_derive/src/shader_defs.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,11 @@ pub fn derive_shader_defs(input: TokenStream) -> TokenStream {
4747
#shader_defs_len
4848
}
4949

50-
fn get_shader_def(&self, index: usize) -> Option<&str> {
50+
fn get_shader_def(&self, index: usize) -> Option<(&str, bool)> {
5151
use #bevy_render_path::shader::ShaderDef;
5252
match index {
53-
#(#shader_def_indices => if self.#shader_def_idents.is_defined() {
54-
Some(#shader_defs)
55-
} else {
56-
None
53+
#(#shader_def_indices => {
54+
Some((#shader_defs, self.#shader_def_idents.is_defined()))
5755
},)*
5856
_ => None,
5957
}

crates/bevy_render/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,7 @@ impl Plugin for RenderPlugin {
146146
stage::RENDER_GRAPH_SYSTEMS,
147147
render_graph::render_graph_schedule_executor_system,
148148
)
149-
.add_system_to_stage(stage::DRAW, pipeline::draw_render_pipelines_system)
150-
.add_system_to_stage(stage::POST_RENDER, shader::clear_shader_defs_system);
149+
.add_system_to_stage(stage::DRAW, pipeline::draw_render_pipelines_system);
151150

152151
if app.resources().get::<Msaa>().is_none() {
153152
app.init_resource::<Msaa>();

crates/bevy_render/src/shader/shader_defs.rs

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use bevy_asset::{Asset, Assets, Handle};
22

33
use crate::{pipeline::RenderPipelines, Texture};
44
pub use bevy_derive::ShaderDefs;
5-
use bevy_ecs::{Query, Res};
5+
use bevy_ecs::{Changed, Mut, Query, Res};
66

77
/// Something that can either be "defined" or "not defined". This is used to determine if a "shader def" should be considered "defined"
88
pub trait ShaderDef {
@@ -12,7 +12,7 @@ pub trait ShaderDef {
1212
/// A collection of "shader defs", which define compile time definitions for shaders.
1313
pub trait ShaderDefs {
1414
fn shader_defs_len(&self) -> usize;
15-
fn get_shader_def(&self, index: usize) -> Option<&str>;
15+
fn get_shader_def(&self, index: usize) -> Option<(&str, bool)>;
1616
fn iter_shader_defs(&self) -> ShaderDefIterator;
1717
}
1818

@@ -31,7 +31,7 @@ impl<'a> ShaderDefIterator<'a> {
3131
}
3232
}
3333
impl<'a> Iterator for ShaderDefIterator<'a> {
34-
type Item = &'a str;
34+
type Item = (&'a str, bool);
3535

3636
fn next(&mut self) -> Option<Self::Item> {
3737
loop {
@@ -40,9 +40,7 @@ impl<'a> Iterator for ShaderDefIterator<'a> {
4040
}
4141
let shader_def = self.shader_defs.get_shader_def(self.index);
4242
self.index += 1;
43-
if shader_def.is_some() {
44-
return shader_def;
45-
}
43+
return shader_def;
4644
}
4745
}
4846
}
@@ -60,55 +58,45 @@ impl ShaderDef for Option<Handle<Texture>> {
6058
}
6159

6260
/// Updates [RenderPipelines] with the latest [ShaderDefs]
63-
pub fn shader_defs_system<T>(mut query: Query<(&T, &mut RenderPipelines)>)
61+
pub fn shader_defs_system<T>(mut query: Query<(&T, &mut RenderPipelines), Changed<T>>)
6462
where
6563
T: ShaderDefs + Send + Sync + 'static,
6664
{
67-
for (shader_defs, mut render_pipelines) in query.iter_mut() {
68-
for shader_def in shader_defs.iter_shader_defs() {
69-
for render_pipeline in render_pipelines.pipelines.iter_mut() {
70-
render_pipeline
71-
.specialization
72-
.shader_specialization
73-
.shader_defs
74-
.insert(shader_def.to_string());
75-
}
76-
}
77-
}
65+
query.iter_mut().for_each(update_render_pipelines)
7866
}
7967

80-
/// Clears each [RenderPipelines]' shader defs collection
81-
pub fn clear_shader_defs_system(mut query: Query<&mut RenderPipelines>) {
82-
for mut render_pipelines in query.iter_mut() {
68+
/// Insert defined shader defs and remove undefined ones from render pipelines.
69+
fn update_render_pipelines<T>(q: (&T, Mut<RenderPipelines>))
70+
where
71+
T: ShaderDefs + Send + Sync + 'static,
72+
{
73+
let (shader_defs, mut render_pipelines) = q;
74+
for (shader_def, is_defined) in shader_defs.iter_shader_defs() {
8375
for render_pipeline in render_pipelines.pipelines.iter_mut() {
84-
render_pipeline
76+
let shader_defs = &mut render_pipeline
8577
.specialization
8678
.shader_specialization
87-
.shader_defs
88-
.clear();
79+
.shader_defs;
80+
let s = shader_def.to_string();
81+
if is_defined {
82+
shader_defs.insert(s);
83+
} else {
84+
shader_defs.remove(&s);
85+
}
8986
}
9087
}
9188
}
9289

9390
/// Updates [RenderPipelines] with the latest [ShaderDefs] from a given asset type
9491
pub fn asset_shader_defs_system<T: Asset>(
9592
assets: Res<Assets<T>>,
96-
mut query: Query<(&Handle<T>, &mut RenderPipelines)>,
93+
mut query: Query<(&Handle<T>, &mut RenderPipelines), Changed<Handle<T>>>,
9794
) where
9895
T: ShaderDefs + Send + Sync + 'static,
9996
{
100-
for (asset_handle, mut render_pipelines) in query.iter_mut() {
101-
if let Some(asset_handle) = assets.get(asset_handle) {
102-
let shader_defs = asset_handle;
103-
for shader_def in shader_defs.iter_shader_defs() {
104-
for render_pipeline in render_pipelines.pipelines.iter_mut() {
105-
render_pipeline
106-
.specialization
107-
.shader_specialization
108-
.shader_defs
109-
.insert(shader_def.to_string());
110-
}
111-
}
112-
}
113-
}
97+
query
98+
.iter_mut()
99+
// (Handle<T>, _) -> (&T, _)
100+
.filter_map(|(h, p)| assets.get(h).map(|a| (a, p)))
101+
.for_each(update_render_pipelines);
114102
}

0 commit comments

Comments
 (0)