Skip to content

Commit f7ca21e

Browse files
committed
WESL: Suport importing shader from asset source
1 parent 2146899 commit f7ca21e

File tree

5 files changed

+54
-18
lines changed

5 files changed

+54
-18
lines changed

crates/bevy_shader/src/shader_cache.rs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ pub struct ShaderCache<ShaderModule, RenderDevice> {
6565
&ValidateShader,
6666
) -> Result<ShaderModule, PipelineCacheError>,
6767
#[cfg(feature = "shader_format_wesl")]
68-
asset_paths: HashMap<wesl::syntax::ModulePath, AssetId<Shader>>,
68+
asset_paths: HashMap<wesl::ModulePath, AssetId<Shader>>,
6969
shaders: HashMap<AssetId<Shader>, Shader>,
7070
import_path_shaders: HashMap<ShaderImport, AssetId<Shader>>,
7171
waiting_on_import: HashMap<ShaderImport, Vec<AssetId<Shader>>>,
@@ -210,7 +210,7 @@ impl<ShaderModule, RenderDevice> ShaderCache<ShaderModule, RenderDevice> {
210210
if let ShaderImport::AssetPath(path) = shader.import_path() {
211211
let shader_resolver =
212212
ShaderResolver::new(&self.asset_paths, &self.shaders);
213-
let module_path = wesl::syntax::ModulePath::from_path(path);
213+
let module_path = wesl_module_path_from_asset_path(path);
214214
let mut compiler_options = wesl::CompileOptions {
215215
imports: true,
216216
condcomp: true,
@@ -361,7 +361,7 @@ impl<ShaderModule, RenderDevice> ShaderCache<ShaderModule, RenderDevice> {
361361
&& let ShaderImport::AssetPath(path) = shader.import_path()
362362
{
363363
self.asset_paths
364-
.insert(wesl::syntax::ModulePath::from_path(path), id);
364+
.insert(wesl_module_path_from_asset_path(path), id);
365365
}
366366
self.shaders.insert(id, shader);
367367
pipelines_to_queue
@@ -379,14 +379,14 @@ impl<ShaderModule, RenderDevice> ShaderCache<ShaderModule, RenderDevice> {
379379

380380
#[cfg(feature = "shader_format_wesl")]
381381
pub struct ShaderResolver<'a> {
382-
asset_paths: &'a HashMap<wesl::syntax::ModulePath, AssetId<Shader>>,
382+
asset_paths: &'a HashMap<wesl::ModulePath, AssetId<Shader>>,
383383
shaders: &'a HashMap<AssetId<Shader>, Shader>,
384384
}
385385

386386
#[cfg(feature = "shader_format_wesl")]
387387
impl<'a> ShaderResolver<'a> {
388388
pub fn new(
389-
asset_paths: &'a HashMap<wesl::syntax::ModulePath, AssetId<Shader>>,
389+
asset_paths: &'a HashMap<wesl::ModulePath, AssetId<Shader>>,
390390
shaders: &'a HashMap<AssetId<Shader>, Shader>,
391391
) -> Self {
392392
Self {
@@ -400,7 +400,7 @@ impl<'a> ShaderResolver<'a> {
400400
impl<'a> wesl::Resolver for ShaderResolver<'a> {
401401
fn resolve_source(
402402
&self,
403-
module_path: &wesl::syntax::ModulePath,
403+
module_path: &wesl::ModulePath,
404404
) -> Result<alloc::borrow::Cow<'_, str>, wesl::ResolveError> {
405405
let asset_id = self.asset_paths.get(module_path).ok_or_else(|| {
406406
wesl::ResolveError::ModuleNotFound(module_path.clone(), "Invalid asset id".to_string())
@@ -411,6 +411,27 @@ impl<'a> wesl::Resolver for ShaderResolver<'a> {
411411
}
412412
}
413413

414+
#[cfg(feature = "shader_format_wesl")]
415+
fn wesl_module_path_from_asset_path(path: &String) -> wesl::ModulePath {
416+
use bevy_asset::{io::AssetSourceId, AssetPath};
417+
use std::path::PathBuf;
418+
419+
let asset_path = AssetPath::from(path);
420+
if let AssetSourceId::Name(source) = asset_path.source() {
421+
let mut comp = vec!["bevy_asset".to_string()];
422+
let mut path = PathBuf::new();
423+
path.push(source.as_ref());
424+
path.push(asset_path.path());
425+
comp.extend(wesl::ModulePath::from_path(path).components);
426+
wesl::ModulePath {
427+
origin: wesl::syntax::PathOrigin::Package,
428+
components: comp,
429+
}
430+
} else {
431+
wesl::ModulePath::from_path(asset_path.path())
432+
}
433+
}
434+
414435
/// Type of error returned by a `PipelineCache` when the creation of a GPU pipeline object failed.
415436
#[cfg_attr(
416437
not(target_arch = "wasm32"),
Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
import super::util::make_polka_dots;
2-
3-
struct VertexOutput {
4-
@builtin(position) position: vec4<f32>,
5-
@location(2) uv: vec2<f32>,
6-
}
2+
import bevy_asset::embedded::shader_material_wesl::files::vertex_attr;
73

84
struct CustomMaterial {
95
// Needed for 16-bit alignment on WebGL2
@@ -14,7 +10,7 @@ struct CustomMaterial {
1410

1511
@fragment
1612
fn fragment(
17-
mesh: VertexOutput,
13+
mesh: vertex_attr::VertexOutput,
1814
) -> @location(0) vec4<f32> {
1915
return make_polka_dots(mesh.uv, material.time.x);
2016
}
File renamed without changes.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
struct VertexOutput {
2+
@builtin(position) position: vec4<f32>,
3+
@location(2) uv: vec2<f32>,
4+
}

examples/shader/shader_material_wesl.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! A shader that uses the WESL shading language.
22
3+
use bevy::asset::embedded_asset;
34
use bevy::{
45
mesh::MeshVertexBufferLayoutRef,
56
pbr::{MaterialPipeline, MaterialPipelineKey},
@@ -12,7 +13,8 @@ use bevy::{
1213
};
1314

1415
/// This example uses shader source files from the assets subdirectory
15-
const FRAGMENT_SHADER_ASSET_PATH: &str = "shaders/custom_material.wesl";
16+
const FRAGMENT_SHADER_ASSET_PATH: &str =
17+
"embedded://shader_material_wesl/files/custom_material.wesl";
1618

1719
fn main() {
1820
App::new()
@@ -37,13 +39,26 @@ pub struct CustomMaterialPlugin;
3739
#[derive(Resource)]
3840
struct UtilityShader(Handle<Shader>);
3941

42+
#[expect(
43+
dead_code,
44+
reason = "used to kept a strong handle, shader is referenced by the material"
45+
)]
46+
#[derive(Resource)]
47+
struct VertexAttrShader(Handle<Shader>);
48+
4049
impl Plugin for CustomMaterialPlugin {
4150
fn build(&self, app: &mut App) {
42-
let handle = app
43-
.world_mut()
44-
.resource_mut::<AssetServer>()
45-
.load::<Shader>("shaders/util.wesl");
46-
app.insert_resource(UtilityShader(handle));
51+
embedded_asset!(app, "examples/shader", "files/custom_material.wesl");
52+
embedded_asset!(app, "examples/shader", "files/vertex_attr.wesl");
53+
embedded_asset!(app, "examples/shader", "files/util.wesl");
54+
55+
let asset_server = app.world_mut().resource_mut::<AssetServer>();
56+
let utils_handle =
57+
asset_server.load::<Shader>("embedded://shader_material_wesl/files/util.wesl");
58+
let vertex_attr_handle =
59+
asset_server.load::<Shader>("embedded://shader_material_wesl/files/vertex_attr.wesl");
60+
app.insert_resource(UtilityShader(utils_handle))
61+
.insert_resource(VertexAttrShader(vertex_attr_handle));
4762
}
4863
}
4964

0 commit comments

Comments
 (0)