daneelsan / minimal-zig-wasm-canvas

A minimal example showing how HTML5's canvas, wasm memory and zig can interact.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Minimal zig-wasm-canvas example

A minimal example showing how HTML5's canvas, wasm memory and zig can interact.

https://daneelsan.github.io/minimal-zig-wasm-canvas/

checkerboard

This example was mostly adapted from: https://wasmbyexample.dev/examples/reading-and-writing-graphics/reading-and-writing-graphics.rust.en-us.html. The difference (aside from using Zig instead of Rust), is that this example does not depend on any external package, library or extra bindings. As with most Zig related projects, the zig command is everything you will need.

Summary

checkerboard.zig defines a global 8 by 8 pixel array: checkerboard_buffer. There are two functions exported: getCheckerboardBufferPointer() and colorCheckerboard(...). getCheckerboardBufferPointer() returns a pointer to the start of checkerboard_buffer, which will be used inside script.js (described later). The other function, colorCheckerboard(...), is in charge of (re-)coloring the different squares in the checkerboard according to colors passed down by script.js.

checkerboard.zig is compiled into the wasm module checkerboard.wasm by build.zig (see the Build Section).

script.js first creates a WebAssembly.Memory, named memory, which will be used by the wasm module's memory. Next step is to compile and instantiate the fetched wasm module using WebAssembly.instantiateStreaming(). The returned object is a Promise which contains the instance field (WebAssembly.Instance). This is where all the exported symbols from checkerboard.wasm will be stored.

What follows is mostly straightforward:

  • Create a Uint8Array from the WebAssembly.Memory memory buffer, called wasmMemoryArray.
  • Get the "checkerboard" canvas defined in index.html and create an ImageData object from the canvas' context, called imageData.
  • In a loop:
    • Call colorCheckerboard(...), passing down random RGB colors. This will modify the values inside checkerboard_buffer.
    • Extract the contents of the checkerboard_buffer, which is an slice of wasmMemoryArray offseted by getCheckerboardBufferPointer() and of length 8 * 8 * 4 (bytes).
    • Copy the contents of the previous slice, i.e. the contents of checkerboard_buffer, into the imageData's data.
    • Put the imageData into the canvas.

Build

The default (and only) target for this example is wasm32-freestanding-musl.

The latest zig version used to build this project is:

$ zig version
0.12.0-dev.2341+92211135f

To build the wasm module, run:

$ zig build

$ ls zig-out/lib/ checkerboard.*
checkerboard.wasm

$ wc -c zig-out/bin/checkerboard.wasm 
580 zig-out/bin/checkerboard.wasm

Note: build.zig specifies various wasm-ld parameters. For example, it sets the initial memory size and maximum size to be 2 pages, where each page consists of 64kB. Use the --verbose flag to see the complete list of flags the build uses.

Run

Start up the server in this repository's directory:

python3 -m http.server

Go to your favorite browser and type to the URL localhost:8000. You should see the checkboard changing colors.

Resources

About

A minimal example showing how HTML5's canvas, wasm memory and zig can interact.


Languages

Language:Zig 50.8%Language:JavaScript 41.5%Language:HTML 7.8%