Skip to content

Commit 7621eaa

Browse files
tychedeliacatilac
andauthored
Initial WASM implementation (#29)
Co-authored-by: Moon D. <[email protected]>
1 parent b107cc7 commit 7621eaa

File tree

12 files changed

+595
-42
lines changed

12 files changed

+595
-42
lines changed

Cargo.lock

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,13 @@ glfw = { version = "0.60.0", features = ["wayland"] }
3737
[[example]]
3838
name = "rectangle"
3939
path = "examples/rectangle.rs"
40+
41+
[[example]]
42+
name = "background_image"
43+
path = "examples/background_image.rs"
44+
45+
[profile.wasm-release]
46+
inherits = "release"
47+
opt-level = "z"
48+
lto = "fat"
49+
codegen-units = 1

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,43 @@ libprocessing is an experimental native library with the goal of supporting the
88

99
You'll need to install the Rust toolchain to work on this project. Most users will want to install Rust via [`rustup`](https://rustup.rs/), which helps manage Rust toolchain versions.
1010

11+
### Build commands
12+
13+
This project uses [just](https://github.com/casey/just) as a command runner. Run `just` to see available commands.
14+
15+
## Building for web
16+
17+
The `processing_wasm` crate provides WebAssembly bindings that expose a JavaScript API mirroring the C FFI.
18+
19+
### Requirements
20+
21+
Install [wasm-pack](https://rustwasm.github.io/wasm-pack/):
22+
23+
```bash
24+
cargo install wasm-pack
25+
```
26+
27+
You'll also need the wasm32 target:
28+
29+
```bash
30+
rustup target add wasm32-unknown-unknown
31+
```
32+
33+
### Build
34+
35+
```bash
36+
just wasm-build
37+
```
38+
39+
This outputs the package to `target/wasm/`.
40+
41+
### Run the example
42+
43+
```bash
44+
just wasm-serve
45+
```
46+
47+
1148
## Contributing
1249

1350
We want your help building this library! You can see a list of outstanding tasks in our [issues](https://github.com/processing/libprocessing). However, while we're still in the early phases, consider checking in with us first in the `#devs-chat` channel on [Discord](https://discord.gg/h99u95nU7q) to coordinate our efforts.

crates/processing_render/Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,10 @@ objc2 = { version = "0.6", default-features = false }
2121
objc2-app-kit = { version = "0.3", features = ["NSWindow", "NSView"] }
2222

2323
[target.'cfg(target_os = "windows")'.dependencies]
24-
windows = { version = "0.58", features = ["Win32_Foundation", "Win32_System_LibraryLoader"] }
24+
windows = { version = "0.58", features = ["Win32_Foundation", "Win32_System_LibraryLoader"] }
25+
26+
[target.'cfg(target_arch = "wasm32")'.dependencies]
27+
wasm-bindgen = "0.2"
28+
wasm-bindgen-futures = "0.4"
29+
js-sys = "0.3"
30+
web-sys = { version = "0.3", features = ["Window", "Document", "HtmlCanvasElement"] }

crates/processing_render/src/image.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,57 @@ pub fn create(
107107
.expect("Failed to run new PImage system")
108108
}
109109

110+
pub fn load_start(world: &mut World, path: PathBuf) -> Handle<Image> {
111+
world.get_asset_server().load(path)
112+
}
113+
114+
pub fn is_loaded(world: &World, handle: &Handle<Image>) -> bool {
115+
matches!(
116+
world.get_asset_server().load_state(handle),
117+
LoadState::Loaded
118+
)
119+
}
120+
121+
#[cfg(target_arch = "wasm32")]
122+
pub fn from_handle(world: &mut World, handle: Handle<Image>) -> Result<Entity> {
123+
fn from_handle_inner(In(handle): In<Handle<Image>>, world: &mut World) -> Result<Entity> {
124+
let images = world.resource::<Assets<Image>>();
125+
let image = images.get(&handle).ok_or(ProcessingError::ImageNotFound)?;
126+
127+
let size = image.texture_descriptor.size;
128+
let texture_format = image.texture_descriptor.format;
129+
let pixel_size = match texture_format {
130+
TextureFormat::Rgba8Unorm | TextureFormat::Rgba8UnormSrgb => 4usize,
131+
TextureFormat::Rgba16Float => 8,
132+
TextureFormat::Rgba32Float => 16,
133+
_ => panic!("Unsupported texture format for readback"),
134+
};
135+
let readback_buffer_size = size.width * size.height * pixel_size as u32;
136+
137+
let render_device = world.resource::<RenderDevice>();
138+
let readback_buffer = render_device.create_buffer(&BufferDescriptor {
139+
label: Some("PImage Readback Buffer"),
140+
size: readback_buffer_size as u64,
141+
usage: BufferUsages::COPY_DST | BufferUsages::MAP_READ,
142+
mapped_at_creation: false,
143+
});
144+
145+
Ok(world
146+
.spawn(PImage {
147+
handle: handle.clone(),
148+
readback_buffer,
149+
pixel_size,
150+
texture_format,
151+
size,
152+
})
153+
.id())
154+
}
155+
156+
world
157+
.run_system_cached_with(from_handle_inner, handle)
158+
.expect("Failed to run from_handle system")
159+
}
160+
110161
pub fn load(world: &mut World, path: PathBuf) -> Result<Entity> {
111162
fn load_inner(In(path): In<PathBuf>, world: &mut World) -> Result<Entity> {
112163
let handle = world.get_asset_server().load(path);

0 commit comments

Comments
 (0)