mirror of https://github.com/sotrh/learn-wgpu
wasm is building
parent
e683f9de4c
commit
0da913d253
@ -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
|
@ -1,81 +1,97 @@
|
|||||||
use anyhow::*;
|
use anyhow::*;
|
||||||
|
use fs_extra::copy_items;
|
||||||
|
use fs_extra::dir::CopyOptions;
|
||||||
use glob::glob;
|
use glob::glob;
|
||||||
use std::fs::{read_to_string, write};
|
use naga::back::wgsl;
|
||||||
use std::path::PathBuf;
|
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 {
|
pub fn load_shader(src_path: PathBuf) -> Result<()> {
|
||||||
src: String,
|
let extension = src_path
|
||||||
src_path: PathBuf,
|
.extension()
|
||||||
spv_path: PathBuf,
|
.context("File has no extension")?
|
||||||
kind: shaderc::ShaderKind,
|
.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 {
|
let info = naga::valid::Validator::new(
|
||||||
pub fn load(src_path: PathBuf) -> Result<Self> {
|
naga::valid::ValidationFlags::all(),
|
||||||
let extension = src_path
|
naga::valid::Capabilities::empty(),
|
||||||
.extension()
|
)
|
||||||
.context("File has no extension")?
|
.validate(&module)?;
|
||||||
.to_str()
|
std::fs::write(wgsl_path, wgsl::write_string(&module, &info)?)?;
|
||||||
.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 src = read_to_string(src_path.clone())?;
|
// let flags = spv::WriterFlags::DEBUG | spv::WriterFlags::ADJUST_COORDINATE_SPACE;
|
||||||
let spv_path = src_path.with_extension(format!("{}.spv", extension));
|
// 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 {
|
Ok(())
|
||||||
src,
|
|
||||||
src_path,
|
|
||||||
spv_path,
|
|
||||||
kind,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
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/
|
// Collect all shaders recursively within /src/
|
||||||
let mut shader_paths = [
|
// UDPATED!
|
||||||
glob("./res/**/*.vert")?,
|
let shader_paths = {
|
||||||
glob("./res/**/*.frag")?,
|
let mut data = Vec::new();
|
||||||
glob("./res/**/*.comp")?,
|
data.extend(glob("./res/**/*.vert")?);
|
||||||
];
|
data.extend(glob("./res/**/*.frag")?);
|
||||||
|
data.extend(glob("./res/**/*.comp")?);
|
||||||
|
data
|
||||||
|
};
|
||||||
|
|
||||||
// This could be parallelized
|
// UPDATED!
|
||||||
let shaders = shader_paths
|
// This is parallelized
|
||||||
.iter_mut()
|
shader_paths
|
||||||
.flatten()
|
.into_par_iter()
|
||||||
.map(|glob_result| ShaderData::load(glob_result?))
|
.map(|glob_result| load_shader(glob_result?))
|
||||||
.collect::<Vec<Result<_>>>()
|
.collect::<Vec<Result<_>>>()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<Result<Vec<_>>>()?;
|
.collect::<Result<Vec<_>>>()?;
|
||||||
|
|
||||||
let mut compiler = shaderc::Compiler::new().context("Unable to create shader compiler")?;
|
// This tells cargo to rerun this script if something in /res/ changes.
|
||||||
|
println!("cargo:rerun-if-changed=res/*");
|
||||||
// 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()
|
|
||||||
);
|
|
||||||
|
|
||||||
let compiled = compiler.compile_into_spirv(
|
let out_dir = env::var("OUT_DIR")?;
|
||||||
&shader.src,
|
let mut copy_options = CopyOptions::new();
|
||||||
shader.kind,
|
let mut paths_to_copy = Vec::new();
|
||||||
shader.src_path.to_str().unwrap(),
|
copy_options.overwrite = true;
|
||||||
"main",
|
paths_to_copy.push("res/");
|
||||||
None,
|
copy_items(&paths_to_copy, out_dir, ©_options)?;
|
||||||
)?;
|
|
||||||
write(shader.spv_path, compiled.as_binary_u8())?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
struct FragmentOutput {
|
||||||
|
[[location(0)]] fColor: vec4<f32>;
|
||||||
|
};
|
||||||
|
|
||||||
|
var<private> fColor: vec4<f32>;
|
||||||
|
|
||||||
|
fn main1() {
|
||||||
|
fColor = vec4<f32>(f32(1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[stage(fragment)]]
|
||||||
|
fn main() -> FragmentOutput {
|
||||||
|
main1();
|
||||||
|
let e3: vec4<f32> = fColor;
|
||||||
|
return FragmentOutput(e3);
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
struct VertexOutput {
|
||||||
|
[[builtin(position)]] member: vec4<f32>;
|
||||||
|
};
|
||||||
|
|
||||||
|
var<private> aPosition1: vec2<f32>;
|
||||||
|
var<private> gl_Position: vec4<f32>;
|
||||||
|
|
||||||
|
fn main1() {
|
||||||
|
let e2: vec2<f32> = aPosition1;
|
||||||
|
gl_Position = vec4<f32>(e2, f32(0), f32(1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[stage(vertex)]]
|
||||||
|
fn main([[location(0)]] aPosition: vec2<f32>) -> VertexOutput {
|
||||||
|
aPosition1 = aPosition;
|
||||||
|
main1();
|
||||||
|
let e5: vec4<f32> = gl_Position;
|
||||||
|
return VertexOutput(e5);
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<!--
|
||||||
|
This is adapted from https://github.com/gfx-rs/wgpu/blob/master/run-wasm-example.sh
|
||||||
|
|
||||||
|
Eventually I'll have all the examples create there own components for vuepress to
|
||||||
|
use, but this will do for now.
|
||||||
|
-->
|
||||||
|
<script type="module">
|
||||||
|
import init from "./pong.js";
|
||||||
|
window.addEventListener("load", () => {
|
||||||
|
init();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
Loading…
Reference in New Issue