Skip to content
This repository was archived by the owner on Jun 18, 2021. It is now read-only.

Commit 4c2744b

Browse files
committed
Add web backend
1 parent a96a5fa commit 4c2744b

File tree

9 files changed

+1711
-561
lines changed

9 files changed

+1711
-561
lines changed

Cargo.toml

+100-14
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,26 @@ default = []
2323
# Make Vulkan backend available on platforms where it is by default not, e.g. macOS
2424
vulkan = ["wgn/vulkan-portability"]
2525

26-
[dependencies.wgn]
26+
[target.'cfg(not(target_arch = "wasm32"))'.dependencies.wgn]
2727
package = "wgpu-native"
2828
version = "0.4"
29-
git = "https://github.com/gfx-rs/wgpu"
30-
rev = "39f17e50754aba6beeeabdd868ddfd700f9710c5"
31-
#path = "../wgpu/wgpu-native"
29+
#git = "https://github.com/gfx-rs/wgpu"
30+
#rev = "39f17e50754aba6beeeabdd868ddfd700f9710c5"
31+
path = "../wgpu/wgpu-native"
3232

33-
[dependencies.wgc]
33+
[target.'cfg(not(target_arch = "wasm32"))'.dependencies.wgc]
3434
package = "wgpu-core"
3535
version = "0.1"
36-
git = "https://github.com/gfx-rs/wgpu"
37-
rev = "39f17e50754aba6beeeabdd868ddfd700f9710c5"
38-
#path = "../wgpu/wgpu-core"
36+
#git = "https://github.com/gfx-rs/wgpu"
37+
#rev = "39f17e50754aba6beeeabdd868ddfd700f9710c5"
38+
path = "../wgpu/wgpu-core"
3939

4040
[dependencies.wgt]
4141
package = "wgpu-types"
4242
version = "0.1"
43-
git = "https://github.com/gfx-rs/wgpu"
44-
rev = "39f17e50754aba6beeeabdd868ddfd700f9710c5"
45-
#path = "../wgpu/wgpu-types"
43+
#git = "https://github.com/gfx-rs/wgpu"
44+
#rev = "39f17e50754aba6beeeabdd868ddfd700f9710c5"
45+
path = "../wgpu/wgpu-types"
4646

4747
[dependencies]
4848
arrayvec = "0.5"
@@ -51,11 +51,97 @@ raw-window-handle = "0.3"
5151

5252
[dev-dependencies]
5353
cgmath = "0.17"
54-
env_logger = "0.7"
55-
glsl-to-spirv = "0.1"
54+
#glsl-to-spirv = "0.1"
5655
log = "0.4"
5756
png = "0.15"
58-
winit = "0.20"
57+
winit = { version = "0.22", features = ["web-sys"] }
5958
rand = "0.7.2"
6059
zerocopy = "0.2"
6160
futures = "0.3"
61+
62+
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
63+
env_logger = "0.7"
64+
65+
[target.'cfg(target_arch = "wasm32")'.dependencies]
66+
wasm-bindgen = "0.2.59"
67+
web-sys = { version = "0.3.36", features = [
68+
"Document",
69+
"Navigator",
70+
"Node",
71+
"NodeList",
72+
"Gpu",
73+
"GpuAdapter",
74+
"GpuBindGroup",
75+
"GpuBindGroupBinding",
76+
"GpuBindGroupDescriptor",
77+
"GpuBindGroupLayout",
78+
"GpuBindGroupLayoutBinding",
79+
"GpuBindGroupLayoutDescriptor",
80+
"GpuBlendDescriptor",
81+
"GpuBlendFactor",
82+
"GpuBlendOperation",
83+
"GpuBindingType",
84+
"GpuBuffer",
85+
"GpuBufferBinding",
86+
"GpuBufferDescriptor",
87+
"GpuCanvasContext",
88+
"GpuColorDict",
89+
"GpuColorStateDescriptor",
90+
"GpuCommandBuffer",
91+
"GpuCommandBufferDescriptor",
92+
"GpuCommandEncoder",
93+
"GpuCommandEncoderDescriptor",
94+
"GpuCompareFunction",
95+
"GpuComputePassDescriptor",
96+
"GpuComputePassEncoder",
97+
"GpuComputePipeline",
98+
"GpuComputePipelineDescriptor",
99+
"GpuCullMode",
100+
"GpuDepthStencilStateDescriptor",
101+
"GpuDevice",
102+
"GpuDeviceDescriptor",
103+
"GpuFrontFace",
104+
"GpuIndexFormat",
105+
"GpuInputStepMode",
106+
"GpuLimits",
107+
"GpuLoadOp",
108+
"GpuPipelineLayout",
109+
"GpuPipelineLayoutDescriptor",
110+
"GpuPowerPreference",
111+
"GpuPrimitiveTopology",
112+
"GpuProgrammableStageDescriptor",
113+
"GpuQueue",
114+
"GpuRasterizationStateDescriptor",
115+
"GpuRenderPassColorAttachmentDescriptor",
116+
"GpuRenderPassDepthStencilAttachmentDescriptor",
117+
"GpuRenderPassDescriptor",
118+
"GpuRenderPassEncoder",
119+
"GpuRenderPipeline",
120+
"GpuRenderPipelineDescriptor",
121+
"GpuRequestAdapterOptions",
122+
"GpuSampler",
123+
"GpuShaderModule",
124+
"GpuShaderModuleDescriptor",
125+
"GpuStencilOperation",
126+
"GpuStencilStateFaceDescriptor",
127+
"GpuStoreOp",
128+
"GpuSwapChain",
129+
"GpuSwapChainDescriptor",
130+
"GpuTexture",
131+
"GpuTextureFormat",
132+
"GpuTextureViewDimension",
133+
"GpuTextureView",
134+
"GpuVertexAttributeDescriptor",
135+
"GpuVertexBufferLayoutDescriptor",
136+
"GpuVertexFormat",
137+
"GpuVertexStateDescriptor",
138+
"GpuVertexAttributeDescriptor",
139+
"HtmlCanvasElement",
140+
"Window",
141+
]}
142+
js-sys = "0.3.36"
143+
wasm-bindgen-futures = "0.4.9"
144+
145+
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
146+
console_error_panic_hook = "0.1.6"
147+
console_log = "0.1.2"

README.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,19 @@ The `hello-triangle` and `hello-compute` examples show bare-bones setup without
3434
cargo run --example hello-compute 1 2 3 4
3535
```
3636

37+
#### Run Examples on the Web (`wasm32-unknown-unknown`)
38+
39+
To run examples on the `wasm32-unknown-unknown` target, first build the example as usual, then run `wasm-bindgen`:
40+
41+
```bash
42+
# Install or update wasm-bindgen-cli
43+
cargo install -f wasm-bindgen-cli
44+
# Build with the wasm target
45+
RUSTFLAGS=--cfg=web_sys_unstable_apis cargo build --example hello-triangle --target wasm32-unknown-unknown
46+
# Generate bindings in a `target/generated` directory
47+
wasm-bindgen target/wasm32-unknown-unknown/debug/examples/hello-triangle.wasm --out-dir target/generated --web
48+
```
49+
3750
## Friends
3851

3952
Shout out to the following projects that work best with wgpu-rs:
@@ -45,7 +58,7 @@ Shout out to the following projects that work best with wgpu-rs:
4558
- [imgui-wgpu](https://github.com/Yatekii/imgui-wgpu-rs) - Dear ImGui interfacing
4659
- [pixels](https://github.com/parasyte/pixels) - the easiest way to create a hardware-accelerated pixel frame buffer
4760
- [kas](https://github.com/dhardy/kas) - tooKit Abstraction System
48-
- [oxiditor](https://github.com/Ruddle/oxidator) - RTS game engine
61+
- [oxidator](https://github.com/Ruddle/oxidator) - RTS game engine
4962
- [nannou](https://github.com/nannou-org/nannou) - a creative coding framework
5063

5164
Also, libraries that have support for wgpu-rs:

examples/hello-compute/main.rs

+19-34
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,9 @@
1-
use std::{convert::TryInto as _, str::FromStr};
21
use zerocopy::AsBytes as _;
2+
use std::convert::TryInto as _;
33

44
async fn run() {
5-
env_logger::init();
6-
7-
// For now this just panics if you didn't pass numbers. Could add proper error handling.
8-
if std::env::args().len() == 1 {
9-
panic!("You must pass a list of positive integers!")
10-
}
11-
let numbers: Vec<u32> = std::env::args()
12-
.skip(1)
13-
.map(|s| u32::from_str(&s).expect("You must pass a list of positive integers!"))
14-
.collect();
15-
16-
println!("Times: {:?}", execute_gpu(numbers).await);
5+
let input = vec![1u32, 2, 3, 4];
6+
log::info!("Times: {:?}", execute_gpu(input).await);
177
}
188

199
async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
@@ -26,14 +16,16 @@ async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
2616
},
2717
wgpu::BackendBit::PRIMARY,
2818
)
19+
.await
2920
.unwrap();
3021

3122
let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor {
3223
extensions: wgpu::Extensions {
3324
anisotropic_filtering: false,
3425
},
3526
limits: wgpu::Limits::default(),
36-
});
27+
})
28+
.await;
3729

3830
let cs = include_bytes!("shader.comp.spv");
3931
let cs_module =
@@ -107,27 +99,20 @@ async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
10799
}
108100
}
109101

110-
fn main() {
111-
futures::executor::block_on(run());
102+
#[cfg(target_arch = "wasm32")]
103+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen::prelude::wasm_bindgen(start))]
104+
pub fn wasm_main() {
105+
console_log::init().expect("could not initialize log");
106+
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
107+
wasm_bindgen_futures::spawn_local(run());
112108
}
113109

114-
#[cfg(test)]
115-
mod tests {
116-
use super::*;
117-
118-
#[test]
119-
fn test_compute_1(){
120-
let input = vec!(1, 2, 3, 4);
121-
futures::executor::block_on(assert_execute_gpu(input, vec!(0, 1, 7, 2)));
122-
}
123-
124-
#[test]
125-
fn test_compute_2(){
126-
let input = vec!(5, 23, 10, 9);
127-
futures::executor::block_on(assert_execute_gpu(input, vec!(5, 15, 6, 19)));
128-
}
110+
#[cfg(target_arch = "wasm32")]
111+
fn main() {
112+
}
129113

130-
async fn assert_execute_gpu(input: Vec<u32>, expected: Vec<u32>){
131-
assert_eq!(execute_gpu(input).await, expected);
132-
}
114+
#[cfg(not(target_arch = "wasm32"))]
115+
fn main() {
116+
env_logger::init();
117+
futures::executor::block_on(run());
133118
}

0 commit comments

Comments
 (0)