Skip to content

Commit e9f52b9

Browse files
committed
Move import_path definitions into shader source (#3976)
This enables shaders to (optionally) define their import path inside their source. This has a number of benefits: 1. enables users to define their own custom paths directly in their assets 2. moves the import path "close" to the asset instead of centralized in the plugin definition, which seems "better" to me. 3. makes "internal hot shader reloading" way more reasonable (see #3966) 4. logically opens the door to importing "parts" of a shader by defining "import_path blocks". ```rust #define_import_path bevy_pbr::mesh_struct struct Mesh { model: mat4x4<f32>; inverse_transpose_model: mat4x4<f32>; // 'flags' is a bit field indicating various options. u32 is 32 bits so we have up to 32 options. flags: u32; }; let MESH_FLAGS_SHADOW_RECEIVER_BIT: u32 = 1u; ```
1 parent b3a1db6 commit e9f52b9

File tree

7 files changed

+57
-27
lines changed

7 files changed

+57
-27
lines changed

crates/bevy_pbr/src/render/mesh.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,11 @@ impl Plugin for MeshRenderPlugin {
4242
);
4343
shaders.set_untracked(
4444
MESH_STRUCT_HANDLE,
45-
Shader::from_wgsl(include_str!("mesh_struct.wgsl"))
46-
.with_import_path("bevy_pbr::mesh_struct"),
45+
Shader::from_wgsl(include_str!("mesh_struct.wgsl")),
4746
);
4847
shaders.set_untracked(
4948
MESH_VIEW_BIND_GROUP_HANDLE,
50-
Shader::from_wgsl(include_str!("mesh_view_bind_group.wgsl"))
51-
.with_import_path("bevy_pbr::mesh_view_bind_group"),
49+
Shader::from_wgsl(include_str!("mesh_view_bind_group.wgsl")),
5250
);
5351

5452
app.add_plugin(UniformComponentPlugin::<MeshUniform>::default());

crates/bevy_pbr/src/render/mesh_struct.wgsl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#define_import_path bevy_pbr::mesh_struct
2+
13
struct Mesh {
24
model: mat4x4<f32>;
35
inverse_transpose_model: mat4x4<f32>;

crates/bevy_pbr/src/render/mesh_view_bind_group.wgsl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#define_import_path bevy_pbr::mesh_view_bind_group
2+
13
struct View {
24
view_proj: mat4x4<f32>;
35
view: mat4x4<f32>;

crates/bevy_render/src/render_resource/shader.rs

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -45,27 +45,29 @@ pub struct Shader {
4545
impl Shader {
4646
pub fn from_wgsl(source: impl Into<Cow<'static, str>>) -> Shader {
4747
let source = source.into();
48+
let shader_imports = SHADER_IMPORT_PROCESSOR.get_imports_from_str(&source);
4849
Shader {
49-
imports: SHADER_IMPORT_PROCESSOR.get_imports_from_str(&source),
50+
imports: shader_imports.imports,
51+
import_path: shader_imports.import_path,
5052
source: Source::Wgsl(source),
51-
import_path: None,
5253
}
5354
}
5455

5556
pub fn from_glsl(source: impl Into<Cow<'static, str>>, stage: naga::ShaderStage) -> Shader {
5657
let source = source.into();
58+
let shader_imports = SHADER_IMPORT_PROCESSOR.get_imports_from_str(&source);
5759
Shader {
58-
imports: SHADER_IMPORT_PROCESSOR.get_imports_from_str(&source),
60+
imports: shader_imports.imports,
61+
import_path: shader_imports.import_path,
5962
source: Source::Glsl(source, stage),
60-
import_path: None,
6163
}
6264
}
6365

6466
pub fn from_spirv(source: impl Into<Cow<'static, [u8]>>) -> Shader {
6567
Shader {
6668
imports: Vec::new(),
67-
source: Source::SpirV(source.into()),
6869
import_path: None,
70+
source: Source::SpirV(source.into()),
6971
}
7072
}
7173

@@ -238,12 +240,16 @@ impl AssetLoader for ShaderLoader {
238240
_ => panic!("unhandled extension: {}", ext),
239241
};
240242

241-
shader.import_path = Some(ShaderImport::AssetPath(
242-
load_context.path().to_string_lossy().to_string(),
243-
));
244-
let imports = SHADER_IMPORT_PROCESSOR.get_imports(&shader);
243+
let shader_imports = SHADER_IMPORT_PROCESSOR.get_imports(&shader);
244+
if shader_imports.import_path.is_some() {
245+
shader.import_path = shader_imports.import_path;
246+
} else {
247+
shader.import_path = Some(ShaderImport::AssetPath(
248+
load_context.path().to_string_lossy().to_string(),
249+
));
250+
}
245251
let mut asset = LoadedAsset::new(shader);
246-
for import in imports {
252+
for import in shader_imports.imports {
247253
if let ShaderImport::AssetPath(asset_path) = import {
248254
let path = PathBuf::from_str(&asset_path)?;
249255
asset.add_dependency(path.into());
@@ -281,6 +287,7 @@ pub enum ProcessShaderError {
281287
pub struct ShaderImportProcessor {
282288
import_asset_path_regex: Regex,
283289
import_custom_path_regex: Regex,
290+
define_import_path_regex: Regex,
284291
}
285292

286293
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
@@ -292,34 +299,48 @@ pub enum ShaderImport {
292299
impl Default for ShaderImportProcessor {
293300
fn default() -> Self {
294301
Self {
295-
import_asset_path_regex: Regex::new(r#"^\s*#\s*import\s*"(.+)""#).unwrap(),
296-
import_custom_path_regex: Regex::new(r"^\s*#\s*import\s*(.+)").unwrap(),
302+
import_asset_path_regex: Regex::new(r#"^\s*#\s*import\s+"(.+)""#).unwrap(),
303+
import_custom_path_regex: Regex::new(r"^\s*#\s*import\s+(.+)").unwrap(),
304+
define_import_path_regex: Regex::new(r"^\s*#\s*define_import_path\s+(.+)").unwrap(),
297305
}
298306
}
299307
}
300308

309+
#[derive(Default)]
310+
pub struct ShaderImports {
311+
imports: Vec<ShaderImport>,
312+
import_path: Option<ShaderImport>,
313+
}
314+
301315
impl ShaderImportProcessor {
302-
pub fn get_imports(&self, shader: &Shader) -> Vec<ShaderImport> {
316+
pub fn get_imports(&self, shader: &Shader) -> ShaderImports {
303317
match &shader.source {
304318
Source::Wgsl(source) => self.get_imports_from_str(source),
305319
Source::Glsl(source, _stage) => self.get_imports_from_str(source),
306-
Source::SpirV(_source) => Vec::new(),
320+
Source::SpirV(_source) => ShaderImports::default(),
307321
}
308322
}
309323

310-
pub fn get_imports_from_str(&self, shader: &str) -> Vec<ShaderImport> {
311-
let mut imports = Vec::new();
324+
pub fn get_imports_from_str(&self, shader: &str) -> ShaderImports {
325+
let mut shader_imports = ShaderImports::default();
312326
for line in shader.lines() {
313327
if let Some(cap) = self.import_asset_path_regex.captures(line) {
314328
let import = cap.get(1).unwrap();
315-
imports.push(ShaderImport::AssetPath(import.as_str().to_string()));
329+
shader_imports
330+
.imports
331+
.push(ShaderImport::AssetPath(import.as_str().to_string()));
316332
} else if let Some(cap) = self.import_custom_path_regex.captures(line) {
317333
let import = cap.get(1).unwrap();
318-
imports.push(ShaderImport::Custom(import.as_str().to_string()));
334+
shader_imports
335+
.imports
336+
.push(ShaderImport::Custom(import.as_str().to_string()));
337+
} else if let Some(cap) = self.define_import_path_regex.captures(line) {
338+
let path = cap.get(1).unwrap();
339+
shader_imports.import_path = Some(ShaderImport::Custom(path.as_str().to_string()));
319340
}
320341
}
321342

322-
imports
343+
shader_imports
323344
}
324345
}
325346

@@ -413,6 +434,11 @@ impl ShaderProcessor {
413434
shader_defs,
414435
&mut final_string,
415436
)?;
437+
} else if SHADER_IMPORT_PROCESSOR
438+
.define_import_path_regex
439+
.is_match(line)
440+
{
441+
// ignore import path lines
416442
} else if *scopes.last().unwrap() {
417443
final_string.push_str(line);
418444
final_string.push('\n');

crates/bevy_sprite/src/mesh2d/mesh.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,11 @@ impl Plugin for Mesh2dRenderPlugin {
5050
);
5151
shaders.set_untracked(
5252
MESH2D_STRUCT_HANDLE,
53-
Shader::from_wgsl(include_str!("mesh2d_struct.wgsl"))
54-
.with_import_path("bevy_sprite::mesh2d_struct"),
53+
Shader::from_wgsl(include_str!("mesh2d_struct.wgsl")),
5554
);
5655
shaders.set_untracked(
5756
MESH2D_VIEW_BIND_GROUP_HANDLE,
58-
Shader::from_wgsl(include_str!("mesh2d_view_bind_group.wgsl"))
59-
.with_import_path("bevy_sprite::mesh2d_view_bind_group"),
57+
Shader::from_wgsl(include_str!("mesh2d_view_bind_group.wgsl")),
6058
);
6159

6260
app.add_plugin(UniformComponentPlugin::<Mesh2dUniform>::default());

crates/bevy_sprite/src/mesh2d/mesh2d_struct.wgsl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#define_import_path bevy_sprite::mesh2d_struct
2+
13
struct Mesh2d {
24
model: mat4x4<f32>;
35
inverse_transpose_model: mat4x4<f32>;

crates/bevy_sprite/src/mesh2d/mesh2d_view_bind_group.wgsl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#define_import_path bevy_sprite::mesh2d_view_bind_group
2+
13
struct View {
24
view_proj: mat4x4<f32>;
35
view: mat4x4<f32>;

0 commit comments

Comments
 (0)