diff --git a/Cargo.lock b/Cargo.lock index cb862caa..df6f09f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,9 +38,9 @@ checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" [[package]] name = "ahash" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "991984e3fd003e7ba02eb724f87a0f997b78677c46c0e91f8424ad7394c9886a" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ "getrandom", "once_cell", @@ -227,9 +227,9 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] name = "bumpalo" -version = "3.7.1" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9df67f7bf9ef8498769f994239c45613ef0c5899415fb58e9add412d2c1a538" +checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" [[package]] name = "bytemuck" @@ -348,12 +348,6 @@ dependencies = [ "libloading 0.7.1", ] -[[package]] -name = "claxon" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" - [[package]] name = "cmake" version = "0.1.46" @@ -440,6 +434,26 @@ dependencies = [ "winit", ] +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501a375961cef1a0d44767200e66e4a559283097e91d0730b1d75dfb2f8a1494" +dependencies = [ + "log", + "web-sys", +] + [[package]] name = "copyless" version = "0.1.5" @@ -568,6 +582,7 @@ dependencies = [ "parking_lot", "stdweb", "thiserror", + "wasm-bindgen", "web-sys", "winapi", ] @@ -856,8 +871,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if 1.0.0", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -1083,9 +1100,9 @@ checksum = "90953f308a79fe6d62a4643e51f848fbfddcd05975a38e69fdf4ab86a7baf7ca" [[package]] name = "instant" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -1168,22 +1185,11 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" -[[package]] -name = "lewton" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" -dependencies = [ - "byteorder", - "ogg", - "tinyvec", -] - [[package]] name = "libc" -version = "0.2.103" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" +checksum = "7b2f96d100e1cf1929e7719b7edb3b90ab5298072638fccd77be9ce942ecdfce" [[package]] name = "libloading" @@ -1306,26 +1312,6 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c64630dcdd71f1a64c435f54885086a0de5d6a12d104d69b165fb7d5286d677" -[[package]] -name = "minimp3" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985438f75febf74c392071a975a29641b420dd84431135a6e6db721de4b74372" -dependencies = [ - "minimp3-sys", - "slice-deque", - "thiserror", -] - -[[package]] -name = "minimp3-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e21c73734c69dc95696c9ed8926a2b393171d98b3f5f5935686a26a487ab9b90" -dependencies = [ - "cc", -] - [[package]] name = "miniz_oxide" version = "0.3.7" @@ -1347,9 +1333,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" dependencies = [ "libc", "log", @@ -1652,15 +1638,6 @@ dependencies = [ "cc", ] -[[package]] -name = "ogg" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" -dependencies = [ - "byteorder", -] - [[package]] name = "once_cell" version = "1.8.0" @@ -1749,9 +1726,9 @@ checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" [[package]] name = "pkg-config" -version = "0.3.20" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb" +checksum = "10e2fcbb64ecbe64c8e040a386c3104d384583af58b956d870aaaf229df6e66d" [[package]] name = "png" @@ -1778,12 +1755,20 @@ dependencies = [ "anyhow", "bytemuck", "cgmath", + "console_error_panic_hook", + "console_log", "fs_extra", + "getrandom", "glob", + "log", + "naga", "pollster", "rand", + "rayon", "rodio", - "shaderc", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", "wgpu", "wgpu_glyph", "winit", @@ -1990,18 +1975,15 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d98f5e557b61525057e2bc142c8cd7f0e70d75dc32852309bec440e6e046bf9" dependencies = [ - "claxon", "cpal", "hound", - "lewton", - "minimp3", ] [[package]] name = "ron" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45005aa836116903a49cf3461474da697cfe66221762c6e95871092009ec86d6" +checksum = "86018df177b1beef6c7c8ef949969c4f7cb9a9344181b92486b23c79995bdaa4" dependencies = [ "base64", "bitflags", @@ -2123,17 +2105,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" -[[package]] -name = "slice-deque" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25" -dependencies = [ - "libc", - "mach", - "winapi", -] - [[package]] name = "slotmap" version = "1.0.6" @@ -2267,21 +2238,6 @@ dependencies = [ "weezl", ] -[[package]] -name = "tinyvec" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" - [[package]] name = "tobj" version = "2.0.4" @@ -2294,7 +2250,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "267a53ebc1139c69d3feedc33a381c382b2e3b0c47f44f48679e90c4a69b8dac" dependencies = [ - "ahash 0.7.5", + "ahash 0.7.6", ] [[package]] @@ -2824,9 +2780,9 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "0.11.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45af76ba5545b61a6904f26cdcf4287329144ae9e12f0c23ec4c9be982d675a6" +checksum = "3bdcbfa4885b32c2b1feb2faeb8b6a76065b752b8f08751b82f994e937687f46" dependencies = [ "arrayvec", "bitflags", @@ -2848,9 +2804,9 @@ dependencies = [ [[package]] name = "wgpu-hal" -version = "0.11.2" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11095a81f4406b1e594dab7dc35d6508409d364e62458f2e5b07b3edc7aca517" +checksum = "0e493835d9edb153d5c8a9d8d016e1811dbe32ddb707a110be1453c7b051d3ec" dependencies = [ "arrayvec", "ash", @@ -2991,7 +2947,9 @@ dependencies = [ "raw-window-handle", "scopeguard", "smithay-client-toolkit", + "wasm-bindgen", "wayland-client", + "web-sys", "winapi", "x11-dl", ] diff --git a/build-wasm.sh b/build-wasm.sh new file mode 100755 index 00000000..0960faba --- /dev/null +++ b/build-wasm.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# Adapted from https://github.com/gfx-rs/wgpu/blob/master/run-wasm-example.sh + +set -e + +cargo build --bin pong --target wasm32-unknown-unknown + +mkdir -p target/wasm-examples/pong +wasm-bindgen --target web --out-dir target/wasm-examples/pong target/wasm32-unknown-unknown/debug/pong.wasm +cp index.template.html target/wasm-examples/pong/index.html \ No newline at end of file diff --git a/code/showcase/pong/Cargo.toml b/code/showcase/pong/Cargo.toml index ae58866d..b102f739 100644 --- a/code/showcase/pong/Cargo.toml +++ b/code/showcase/pong/Cargo.toml @@ -6,7 +6,6 @@ edition = "2018" [dependencies] winit = "0.25" -shaderc = "0.7" anyhow = "1.0" bytemuck = { version = "1.4", features = [ "derive" ] } cgmath = "0.18" @@ -14,10 +13,27 @@ pollster = "0.2" wgpu = { version = "0.11", features = ["spirv"]} wgpu_glyph = "0.15" rand = "0.8" -rodio = "0.14" +rodio = { version = "0.14", default-features = false, features = ["wav"] } +log = "0.4" + +[target.'cfg(target_arch = "wasm32")'.dependencies] +console_error_panic_hook = "0.1.6" +console_log = "0.2.0" +getrandom = { version = "0.2", features = ["js"] } +rodio = { version = "0.14", default-features = false, features = ["wasm-bindgen", "wav"] } +wasm-bindgen = "0.2.76" +wasm-bindgen-futures = "0.4.20" +web-sys = { version = "0.3.53", features = [ + "Document", + "Window", + "Element", +]} +winit = { version = "0.25", features = ["web-sys"] } +wgpu = { version = "0.11", features = ["spirv", "webgl"]} [build-dependencies] anyhow = "1.0" fs_extra = "1.2" glob = "0.3" -shaderc = "0.7" +rayon = "1.4" +naga = { version = "0.7", features = ["glsl-in", "spv-out", "wgsl-out"]} diff --git a/code/showcase/pong/build.rs b/code/showcase/pong/build.rs index 316071c5..e675565b 100644 --- a/code/showcase/pong/build.rs +++ b/code/showcase/pong/build.rs @@ -1,81 +1,97 @@ use anyhow::*; +use fs_extra::copy_items; +use fs_extra::dir::CopyOptions; use glob::glob; -use std::fs::{read_to_string, write}; -use std::path::PathBuf; +use naga::back::wgsl; +use naga::front::glsl::Options; +use naga::front::glsl::Parser; +use rayon::prelude::*; +use std::env; +use std::{fs::read_to_string, path::PathBuf}; -struct ShaderData { - src: String, - src_path: PathBuf, - spv_path: PathBuf, - kind: shaderc::ShaderKind, -} +pub fn load_shader(src_path: PathBuf) -> Result<()> { + let extension = src_path + .extension() + .context("File has no extension")? + .to_str() + .context("Extension cannot be converted to &str")?; + let kind = match extension { + "vert" => naga::ShaderStage::Vertex, + "frag" => naga::ShaderStage::Fragment, + "comp" => naga::ShaderStage::Compute, + _ => bail!("Unsupported shader: {}", src_path.display()), + }; + + let src = read_to_string(src_path.clone())?; + // let spv_path = src_path.with_extension(format!("{}.spv", extension)); + let wgsl_path = src_path.with_extension(format!("{}.wgsl", extension)); + + let mut parser = Parser::default(); + let options = Options::from(kind); + let module = match parser.parse(&options, &src) { + Ok(it) => it, + Err(errors) => { + bail!( + "Failed to compile shader: {}\nErrors:\n{:#?}", + src_path.display(), + errors + ); + } + }; -impl ShaderData { - pub fn load(src_path: PathBuf) -> Result { - let extension = src_path - .extension() - .context("File has no extension")? - .to_str() - .context("Extension cannot be converted to &str")?; - let kind = match extension { - "vert" => shaderc::ShaderKind::Vertex, - "frag" => shaderc::ShaderKind::Fragment, - "comp" => shaderc::ShaderKind::Compute, - _ => bail!("Unsupported shader: {}", src_path.display()), - }; + let info = naga::valid::Validator::new( + naga::valid::ValidationFlags::all(), + naga::valid::Capabilities::empty(), + ) + .validate(&module)?; + std::fs::write(wgsl_path, wgsl::write_string(&module, &info)?)?; - let src = read_to_string(src_path.clone())?; - let spv_path = src_path.with_extension(format!("{}.spv", extension)); + // let flags = spv::WriterFlags::DEBUG | spv::WriterFlags::ADJUST_COORDINATE_SPACE; + // let options = spv::Options { + // flags, + // ..Default::default() + // }; + // let spv = spv::write_vec(&module, &info, &options)?; + // let dis = rspirv::dr::load_words(spv) + // .expect("Unable to disassemble shader") + // .disassemble(); + // std::fs::write(spv_path, &spv)?; - Ok(Self { - src, - src_path, - spv_path, - kind, - }) - } + Ok(()) } fn main() -> Result<()> { + // This tells cargo to rerun this script if something in /src/ changes. + println!("cargo:rerun-if-changed=src/*"); + // Collect all shaders recursively within /src/ - let mut shader_paths = [ - glob("./res/**/*.vert")?, - glob("./res/**/*.frag")?, - glob("./res/**/*.comp")?, - ]; + // UDPATED! + let shader_paths = { + let mut data = Vec::new(); + data.extend(glob("./res/**/*.vert")?); + data.extend(glob("./res/**/*.frag")?); + data.extend(glob("./res/**/*.comp")?); + data + }; - // This could be parallelized - let shaders = shader_paths - .iter_mut() - .flatten() - .map(|glob_result| ShaderData::load(glob_result?)) + // UPDATED! + // This is parallelized + shader_paths + .into_par_iter() + .map(|glob_result| load_shader(glob_result?)) .collect::>>() .into_iter() .collect::>>()?; - let mut compiler = shaderc::Compiler::new().context("Unable to create shader compiler")?; - - // This can't be parallelized. The [shaderc::Compiler] is not - // thread safe. Also, it creates a lot of resources. You could - // spawn multiple processes to handle this, but it would probably - // be better just to only compile shaders that have been changed - // recently. - for shader in shaders { - // This tells cargo to rerun this script if something in /src/ changes. - println!( - "cargo:rerun-if-changed={}", - shader.src_path.as_os_str().to_str().unwrap() - ); + // This tells cargo to rerun this script if something in /res/ changes. + println!("cargo:rerun-if-changed=res/*"); - let compiled = compiler.compile_into_spirv( - &shader.src, - shader.kind, - shader.src_path.to_str().unwrap(), - "main", - None, - )?; - write(shader.spv_path, compiled.as_binary_u8())?; - } + let out_dir = env::var("OUT_DIR")?; + let mut copy_options = CopyOptions::new(); + let mut paths_to_copy = Vec::new(); + copy_options.overwrite = true; + paths_to_copy.push("res/"); + copy_items(&paths_to_copy, out_dir, ©_options)?; Ok(()) } diff --git a/code/showcase/pong/res/shaders/textured.frag.wgsl b/code/showcase/pong/res/shaders/textured.frag.wgsl new file mode 100644 index 00000000..eed0125a --- /dev/null +++ b/code/showcase/pong/res/shaders/textured.frag.wgsl @@ -0,0 +1,17 @@ +struct FragmentOutput { + [[location(0)]] fColor: vec4; +}; + +var fColor: vec4; + +fn main1() { + fColor = vec4(f32(1)); + return; +} + +[[stage(fragment)]] +fn main() -> FragmentOutput { + main1(); + let e3: vec4 = fColor; + return FragmentOutput(e3); +} diff --git a/code/showcase/pong/res/shaders/textured.vert.wgsl b/code/showcase/pong/res/shaders/textured.vert.wgsl new file mode 100644 index 00000000..7584cd45 --- /dev/null +++ b/code/showcase/pong/res/shaders/textured.vert.wgsl @@ -0,0 +1,20 @@ +struct VertexOutput { + [[builtin(position)]] member: vec4; +}; + +var aPosition1: vec2; +var gl_Position: vec4; + +fn main1() { + let e2: vec2 = aPosition1; + gl_Position = vec4(e2, f32(0), f32(1)); + return; +} + +[[stage(vertex)]] +fn main([[location(0)]] aPosition: vec2) -> VertexOutput { + aPosition1 = aPosition; + main1(); + let e5: vec4 = gl_Position; + return VertexOutput(e5); +} diff --git a/code/showcase/pong/src/main.rs b/code/showcase/pong/src/main.rs index ea780a20..be011f76 100644 --- a/code/showcase/pong/src/main.rs +++ b/code/showcase/pong/src/main.rs @@ -24,6 +24,22 @@ fn main() { .unwrap(); window.set_cursor_visible(false); + #[cfg(target_arch = "wasm32")] + { + use winit::platform::web::WindowExtWebSys; + console_log::init_with_level(log::Level::Info).expect("Could't initialize logger"); + std::panic::set_hook(Box::new(console_error_panic_hook::hook)); + web_sys::window() + .and_then(|win| win.document()) + .and_then(|doc| doc.body()) + .and_then(|body| { + body.append_child(&web_sys::Element::from(window.canvas())).ok() + }) + .expect("Couldn't append cavas to document body."); + } + + log::info!("Setup..."); + let mut render = pollster::block_on(render::Render::new(&window, &video_mode)); let mut state = state::State { ball: state::Ball { @@ -90,11 +106,15 @@ fn main() { game_state: state::GameState::MainMenu, }; + log::info!("Sound..."); + let sound_system = sound::SoundSystem::new(); let sound_pack = sound::SoundPack::new(); let mut events = Vec::new(); let mut input = Input::new(); + log::info!("Initializing Systems..."); + let mut menu_system = system::MenuSystem; let mut serving_system = system::ServingSystem::new(); let mut play_system = system::PlaySystem; @@ -108,6 +128,8 @@ fn main() { window.set_visible(true); + log::info!("Event Loop..."); + event_loop.run(move |event, _, control_flow| { *control_flow = if state.game_state == state::GameState::Quiting { ControlFlow::Exit @@ -154,7 +176,7 @@ fn main() { } state::Event::Score(_) => { sound_system.queue(sound_pack.bounce()); - } // _ => {} + } } } events.clear(); diff --git a/code/showcase/pong/src/render/mod.rs b/code/showcase/pong/src/render/mod.rs index 14928083..0a1d1079 100644 --- a/code/showcase/pong/src/render/mod.rs +++ b/code/showcase/pong/src/render/mod.rs @@ -81,8 +81,8 @@ impl Render { &pipeline_layout, config.format, &[Vertex::DESC], - wgpu::include_spirv!("../../res/shaders/textured.vert.spv"), - wgpu::include_spirv!("../../res/shaders/textured.frag.spv"), + wgpu::include_wgsl!("../../res/shaders/textured.vert.wgsl"), + wgpu::include_wgsl!("../../res/shaders/textured.frag.wgsl"), ); let vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor { diff --git a/index.template.html b/index.template.html new file mode 100644 index 00000000..fa0c7366 --- /dev/null +++ b/index.template.html @@ -0,0 +1,23 @@ + + + + + + + + + + + + + \ No newline at end of file