diff --git a/Cargo.lock b/Cargo.lock index cca2536d..0c653df2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2505,6 +2505,9 @@ name = "serde" version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" +dependencies = [ + "serde_derive", +] [[package]] name = "serde_derive" @@ -3409,9 +3412,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -3419,9 +3422,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log", @@ -3434,9 +3437,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-cli-support" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03f35e0387a2c787ca5ee299bfb4259352b2a2184b406f8ee9f978c3c4671645" +checksum = "9d4780c659b883a19ddb7ced365db19f7f45cd182d832ee14de2b7ef52e88a9f" dependencies = [ "anyhow", "base64 0.9.3", @@ -3444,6 +3447,7 @@ dependencies = [ "rustc-demangle", "serde_json", "tempfile", + "unicode-ident", "walrus", "wasm-bindgen-externref-xform", "wasm-bindgen-multi-value-xform", @@ -3458,9 +3462,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-externref-xform" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d010a32a516a793adbea5835eab6f736d11c0cdd10ebe0c762c420f67510244" +checksum = "1d154c3843bf3b635b602ad41b56f505f8f1a25f8a0133fca4bbd0918d74efdc" dependencies = [ "anyhow", "walrus", @@ -3480,9 +3484,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3490,9 +3494,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", @@ -3503,9 +3507,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-multi-value-xform" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b8c8d5dcc451b7e6a9c98d8fd966ff768a1e8f8afb270a829780086f2885ac" +checksum = "c00a577fbd4be358ef8095432189b5c2e6b6e71f5081797c2032572f77d65d26" dependencies = [ "anyhow", "walrus", @@ -3513,15 +3517,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "wasm-bindgen-threads-xform" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d10f9246c4daa911283a7096fc3be9f1fab9e3e36400478a4ab8d7056701420" +checksum = "0aa93941bae037b7b4fac4ecfc132294b828036c5990a806d0e6fd9284297d94" dependencies = [ "anyhow", "walrus", @@ -3530,9 +3534,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-wasm-conventions" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4a5ab217f12f73b7c3ff23cbbbb5d36f7ee97dd65bb0be44beebda887df9002" +checksum = "d8f5de325048d945c90600fdf66b13521f3340d85971287775c36aa99c04466b" dependencies = [ "anyhow", "walrus", @@ -3540,9 +3544,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-wasm-interpreter" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fbb6c773b486889b7c1211d27a7a08eebaf54ec4269380266cadf69e269cd91" +checksum = "f695df44962e3a107436282232a2daa185b8453c16be8ddfb637cd2601f31128" dependencies = [ "anyhow", "log", @@ -3550,6 +3554,19 @@ dependencies = [ "wasm-bindgen-wasm-conventions", ] +[[package]] +name = "wasm-builder" +version = "0.1.0" +dependencies = [ + "anyhow", + "env_logger", + "log", + "rayon", + "serde", + "serde_json", + "wasm-bindgen-cli-support", +] + [[package]] name = "wasmparser" version = "0.59.0" diff --git a/Cargo.toml b/Cargo.toml index 562e2ae2..23f226cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,8 @@ [workspace] resolver = "2" members = [ + "code/wasm-builder", + # beginner tutorials "code/beginner/*", diff --git a/build-wasm.sh b/build-wasm.sh index f7ee5a0f..e3da12c7 100755 --- a/build-wasm.sh +++ b/build-wasm.sh @@ -1,16 +1 @@ -export RES_PATH=learn-wgpu -# (trap 'killall background' INT; -# wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/pong code/showcase/pong -wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/tutorial1_window code/beginner/tutorial1-window -wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/tutorial2_surface code/beginner/tutorial2-surface -wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/tutorial3_pipeline code/beginner/tutorial3-pipeline -wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/tutorial4_buffer code/beginner/tutorial4-buffer -wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/tutorial5_textures code/beginner/tutorial5-textures -wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/tutorial6_uniforms code/beginner/tutorial6-uniforms -wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/tutorial7_instancing code/beginner/tutorial7-instancing -wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/tutorial8_depth code/beginner/tutorial8-depth -wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/tutorial9_models code/beginner/tutorial9-models -wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/tutorial10_lighting code/intermediate/tutorial10-lighting -wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/tutorial11_normals code/intermediate/tutorial11-normals -wasm-pack build --out-dir ../../../docs/.vuepress/components/wasm/tutorial12_camera code/intermediate/tutorial12-camera -# ) +cargo r -p wasm-builder wasm-targets.json \ No newline at end of file diff --git a/code/beginner/tutorial1-window/Cargo.toml b/code/beginner/tutorial1-window/Cargo.toml index 031c0aa9..faab06b5 100644 --- a/code/beginner/tutorial1-window/Cargo.toml +++ b/code/beginner/tutorial1-window/Cargo.toml @@ -23,7 +23,7 @@ pollster = "0.2" console_error_panic_hook = "0.1.6" console_log = "0.2.0" wgpu = { version = "0.15", features = ["webgl"]} -wasm-bindgen = "0.2.76" +wasm-bindgen = "=0.2.84" wasm-bindgen-futures = "0.4.30" web-sys = { version = "0.3.53", features = [ "Document", diff --git a/code/beginner/tutorial9-models/src/model.rs b/code/beginner/tutorial9-models/src/model.rs index 9c7fcf04..563cfa32 100644 --- a/code/beginner/tutorial9-models/src/model.rs +++ b/code/beginner/tutorial9-models/src/model.rs @@ -122,6 +122,7 @@ where camera_bind_group: &'b wgpu::BindGroup, ) { for mesh in &model.meshes { + log::warn!("materials: {}", model.materials.len()); let material = &model.materials[mesh.material]; self.draw_mesh_instanced(mesh, material, instances.clone(), camera_bind_group); } diff --git a/code/beginner/tutorial9-models/src/resources.rs b/code/beginner/tutorial9-models/src/resources.rs index b54dee58..2b49057c 100644 --- a/code/beginner/tutorial9-models/src/resources.rs +++ b/code/beginner/tutorial9-models/src/resources.rs @@ -9,12 +9,11 @@ use crate::{model, texture}; fn format_url(file_name: &str) -> reqwest::Url { let window = web_sys::window().unwrap(); let location = window.location(); - let base = reqwest::Url::parse(&format!( - "{}/{}/", - location.origin().unwrap(), - option_env!("RES_PATH").unwrap_or("res"), - )) - .unwrap(); + let mut origin = location.origin().unwrap(); + if !origin.ends_with("learn-wgpu") { + origin = format!("{}/learn-wgpu", origin); + } + let base = reqwest::Url::parse(&format!("{}/", origin,)).unwrap(); base.join(file_name).unwrap() } diff --git a/code/intermediate/tutorial10-lighting/src/resources.rs b/code/intermediate/tutorial10-lighting/src/resources.rs index 72c97482..2b49057c 100644 --- a/code/intermediate/tutorial10-lighting/src/resources.rs +++ b/code/intermediate/tutorial10-lighting/src/resources.rs @@ -9,11 +9,11 @@ use crate::{model, texture}; fn format_url(file_name: &str) -> reqwest::Url { let window = web_sys::window().unwrap(); let location = window.location(); - let base = reqwest::Url::parse(&format!( - "{}/{}/", - location.origin().unwrap(), - option_env!("RES_PATH").unwrap_or("res"), - )).unwrap(); + let mut origin = location.origin().unwrap(); + if !origin.ends_with("learn-wgpu") { + origin = format!("{}/learn-wgpu", origin); + } + let base = reqwest::Url::parse(&format!("{}/", origin,)).unwrap(); base.join(file_name).unwrap() } diff --git a/code/intermediate/tutorial11-normals/src/resources.rs b/code/intermediate/tutorial11-normals/src/resources.rs index e4c2abb0..505320f2 100644 --- a/code/intermediate/tutorial11-normals/src/resources.rs +++ b/code/intermediate/tutorial11-normals/src/resources.rs @@ -9,12 +9,11 @@ use crate::{model, texture}; fn format_url(file_name: &str) -> reqwest::Url { let window = web_sys::window().unwrap(); let location = window.location(); - let base = reqwest::Url::parse(&format!( - "{}/{}/", - location.origin().unwrap(), - option_env!("RES_PATH").unwrap_or("res"), - )) - .unwrap(); + let mut origin = location.origin().unwrap(); + if !origin.ends_with("learn-wgpu") { + origin = format!("{}/learn-wgpu", origin); + } + let base = reqwest::Url::parse(&format!("{}/", origin,)).unwrap(); base.join(file_name).unwrap() } diff --git a/code/intermediate/tutorial12-camera/src/resources.rs b/code/intermediate/tutorial12-camera/src/resources.rs index 9748884f..505320f2 100644 --- a/code/intermediate/tutorial12-camera/src/resources.rs +++ b/code/intermediate/tutorial12-camera/src/resources.rs @@ -9,11 +9,11 @@ use crate::{model, texture}; fn format_url(file_name: &str) -> reqwest::Url { let window = web_sys::window().unwrap(); let location = window.location(); - let base = reqwest::Url::parse(&format!( - "{}/{}/", - location.origin().unwrap(), - option_env!("RES_PATH").unwrap_or("res"), - )).unwrap(); + let mut origin = location.origin().unwrap(); + if !origin.ends_with("learn-wgpu") { + origin = format!("{}/learn-wgpu", origin); + } + let base = reqwest::Url::parse(&format!("{}/", origin,)).unwrap(); base.join(file_name).unwrap() } diff --git a/code/intermediate/tutorial13-terrain/src/resources.rs b/code/intermediate/tutorial13-terrain/src/resources.rs index f717e230..325cdf0c 100644 --- a/code/intermediate/tutorial13-terrain/src/resources.rs +++ b/code/intermediate/tutorial13-terrain/src/resources.rs @@ -9,11 +9,11 @@ use crate::{model, texture}; fn format_url(file_name: &str) -> reqwest::Url { let window = web_sys::window().unwrap(); let location = window.location(); - let base = reqwest::Url::parse(&format!( - "{}/{}/", - location.origin().unwrap(), - option_env!("RES_PATH").unwrap_or("res"), - )).unwrap(); + let mut origin = location.origin().unwrap(); + if !origin.ends_with("learn-wgpu") { + origin = format!("{}/learn-wgpu", origin); + } + let base = reqwest::Url::parse(&format!("{}/", origin,)).unwrap(); base.join(file_name).unwrap() } diff --git a/code/showcase/pong/.gitignore b/code/showcase/pong/.gitignore new file mode 100644 index 00000000..ffa3bbd2 --- /dev/null +++ b/code/showcase/pong/.gitignore @@ -0,0 +1 @@ +Cargo.lock \ No newline at end of file diff --git a/code/showcase/pong/Cargo.toml b/code/showcase/pong/Cargo.toml index f6e177ed..ad3df043 100644 --- a/code/showcase/pong/Cargo.toml +++ b/code/showcase/pong/Cargo.toml @@ -28,7 +28,7 @@ console_log = "0.2.0" getrandom = { version = "0.2", features = ["js"] } rodio = { version = "0.16", default-features = false, features = ["wasm-bindgen", "wav"] } wasm-bindgen-futures = "0.4.20" -wasm-bindgen = "0.2.76" +wasm-bindgen = "=0.2.84" web-sys = { version = "0.3.53", features = [ "Document", "Window", diff --git a/code/showcase/threading/src/resources.rs b/code/showcase/threading/src/resources.rs index 9748884f..505320f2 100644 --- a/code/showcase/threading/src/resources.rs +++ b/code/showcase/threading/src/resources.rs @@ -9,11 +9,11 @@ use crate::{model, texture}; fn format_url(file_name: &str) -> reqwest::Url { let window = web_sys::window().unwrap(); let location = window.location(); - let base = reqwest::Url::parse(&format!( - "{}/{}/", - location.origin().unwrap(), - option_env!("RES_PATH").unwrap_or("res"), - )).unwrap(); + let mut origin = location.origin().unwrap(); + if !origin.ends_with("learn-wgpu") { + origin = format!("{}/learn-wgpu", origin); + } + let base = reqwest::Url::parse(&format!("{}/", origin,)).unwrap(); base.join(file_name).unwrap() } diff --git a/code/wasm-builder/Cargo.toml b/code/wasm-builder/Cargo.toml new file mode 100644 index 00000000..f48b89e0 --- /dev/null +++ b/code/wasm-builder/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "wasm-builder" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1" +log = "0.4" +env_logger = "0.10" +rayon = "1" +serde = { version = "1", features = ["derive"]} +serde_json = "1" +wasm-bindgen-cli-support = "0.2.84" \ No newline at end of file diff --git a/code/wasm-builder/src/main.rs b/code/wasm-builder/src/main.rs new file mode 100644 index 00000000..5edc093d --- /dev/null +++ b/code/wasm-builder/src/main.rs @@ -0,0 +1,75 @@ +use std::{process::Command, path::PathBuf}; + +use rayon::prelude::{IntoParallelRefIterator, ParallelIterator}; +use wasm_bindgen_cli_support::Bindgen; + +#[derive(Debug, serde::Deserialize, serde::Serialize)] +struct WasmTarget { + package: String, + out: String, +} + +fn main() -> anyhow::Result<()> { + env_logger::init(); + + let input = match std::env::args().skip(1).next() { + Some(s) => s, + None => { + log::info!("No input file supplied"); + std::process::exit(1); + } + }; + + let json = std::fs::read_to_string(input)?; + + let targets: Vec = serde_json::from_str(&json)?; + + // Tell cargo to build all targets as wasm32-unknown-unknown + let mut command = Command::new("cargo"); + + let start_time = std::time::Instant::now(); + + command + .arg("build") + .arg("--release") + .arg("--target") + .arg("wasm32-unknown-unknown"); + for target in &targets { + command.arg("-p").arg(&target.package); + } + command.spawn()?.wait()?; + + let errors = targets + .par_iter() + .map(|target| { + let path = PathBuf::from(&target.out); + + // Ignore contents to prevent cargo-watch looping + std::fs::create_dir_all(&path)?; + std::fs::write(path.join(".gitignore"), "*\n")?; + + Bindgen::new() + .bundler(true)? + .input_path(format!( + "target/wasm32-unknown-unknown/release/{}.wasm", + target.package + )) + .out_name("demo") + .generate(path) + }) + .filter_map(|r| r.err()) + .collect::>(); + + if !errors.is_empty() { + for error in &errors { + log::error!("{}", error); + } + log::error!("Encountered {} error(s)", errors.len()); + std::process::exit(1); + } + + let time_taken = std::time::Instant::now() - start_time; + log::info!("Success fully processed {} target(s) in {:?}", targets.len(), time_taken); + + Ok(()) +} diff --git a/docs/.vuepress/components/WasmExample.vue b/docs/.vuepress/components/WasmExample.vue index 8fa2fb02..2b836fba 100644 --- a/docs/.vuepress/components/WasmExample.vue +++ b/docs/.vuepress/components/WasmExample.vue @@ -40,7 +40,7 @@ export default { async loadExample() { this.loading = true; try { - await import(`./wasm/${this.example}/${this.example}.js`); + await import(`./wasm/${this.example}/demo.js`); } catch (e) { // TODO: Figure out a better way to ignore "control flow" errors if (`${e}` != "Error: Using exceptions for control flow, don't mind me. This isn't actually an error!") { diff --git a/docs/beginner/tutorial9-models/README.md b/docs/beginner/tutorial9-models/README.md index 061bdc83..9c249ef4 100644 --- a/docs/beginner/tutorial9-models/README.md +++ b/docs/beginner/tutorial9-models/README.md @@ -147,11 +147,11 @@ use crate::{model, texture}; fn format_url(file_name: &str) -> reqwest::Url { let window = web_sys::window().unwrap(); let location = window.location(); - let base = reqwest::Url::parse(&format!( - "{}/{}/", - location.origin().unwrap(), - option_env!("RES_PATH").unwrap_or("res"), - )).unwrap(); + let mut origin = location.origin().unwrap(); + if !origin.ends_with("learn-wgpu") { + origin = format!("{}/learn-wgpu", origin); + } + let base = reqwest::Url::parse(&format!("{}/", origin,)).unwrap(); base.join(file_name).unwrap() } diff --git a/docs/showcase/pong/README.md b/docs/showcase/pong/README.md index 355b57b7..d320f530 100644 --- a/docs/showcase/pong/README.md +++ b/docs/showcase/pong/README.md @@ -287,7 +287,7 @@ console_log = "0.2.0" getrandom = { version = "0.2", features = ["js"] } rodio = { version = "0.15", default-features = false, features = ["wasm-bindgen", "wav"] } wasm-bindgen-futures = "0.4.20" -wasm-bindgen = "0.2.76" +wasm-bindgen = "=0.2.84" web-sys = { version = "0.3.53", features = [ "Document", "Window", diff --git a/wasm-targets.json b/wasm-targets.json new file mode 100644 index 00000000..3260fcc4 --- /dev/null +++ b/wasm-targets.json @@ -0,0 +1,50 @@ +[ + { + "package": "tutorial1-window", + "out": "docs/.vuepress/components/wasm/tutorial1_window" + }, + { + "package": "tutorial2-surface", + "out": "docs/.vuepress/components/wasm/tutorial2_surface" + }, + { + "package": "tutorial3-pipeline", + "out": "docs/.vuepress/components/wasm/tutorial3_pipeline" + }, + { + "package": "tutorial4-buffer", + "out": "docs/.vuepress/components/wasm/tutorial4_buffer" + }, + { + "package": "tutorial5-textures", + "out": "docs/.vuepress/components/wasm/tutorial5_textures" + }, + { + "package": "tutorial6-uniforms", + "out": "docs/.vuepress/components/wasm/tutorial6_uniforms" + }, + { + "package": "tutorial7-instancing", + "out": "docs/.vuepress/components/wasm/tutorial7_instancing" + }, + { + "package": "tutorial8-depth", + "out": "docs/.vuepress/components/wasm/tutorial8_depth" + }, + { + "package": "tutorial9-models", + "out": "docs/.vuepress/components/wasm/tutorial9_models" + }, + { + "package": "tutorial10-lighting", + "out": "docs/.vuepress/components/wasm/tutorial10_lighting" + }, + { + "package": "tutorial11-normals", + "out": "docs/.vuepress/components/wasm/tutorial11_normals" + }, + { + "package": "tutorial12-camera", + "out": "docs/.vuepress/components/wasm/tutorial12_camera" + } +] \ No newline at end of file