New Shader

@compute.toys is a playground for WebGPU compute shaders. Everything here is written in WGSL, which is WebGPU's native shader language. For up-to-date information on WGSL, please see the WGSL draft specification. You can also take a tour of WGSL.


@compute.toys supplies keyboard input, mouse input, selectable input textures, custom values controlled by sliders, and the current frame and elapsed time.

Mouse input can be accessed from the mouse struct:
mouse.pos: vec2i
mouse.click: i32
Timing information is in the time struct:
time.frame: u32
time.elapsed: f32
Custom uniforms are in the custom struct:
custom.my_custom_uniform_0: f32
custom.my_custom_uniform_1: f32
Two selectable textures can be accessed from channel0 and channel1:
textureSampleLevel(channel0, bilinear, uv, pass, lod)
textureSampleLevel(channel1, bilinear, uv, pass, lod)
Keyboard input can be accessed from the provided keyDown(keycode: u32) helper function:
keyDown(32) // returns true when the spacebar is pressed


For compute shader input and output @compute.toys provides:
one input texture array pass_in,
one output storage texture array pass_out,
and one output screen storage texture screen.

The shader can write to pass_out, which will be copied into pass_in after the current entrypoint has returned. pass_in will always contain whatever has been written to pass_out during all of the previous entrypoints. The contents of pass_in will not change while an entrypoint is running. pass_in and pass_out are both texture arrays with 4 texture layers. For example, you can access the third layer of pass_in at LOD 0 and coordinate (1,1) by using the built-in helper function:
passLoad(2, vec2i(1,1), 0)


@compute.toys also provides an experimental WGSL preprocessor. It currently allows the use of a handful of basic directives:
  • #define NAME VALUE for simple macros (function-like parameter substitution is not yet supported)
  • #include "PATH" for accessing built-in libraries
  • #workgroup_count ENTRYPOINT X Y Z for specifying how many workgroups should be dispatched for an entrypoint
  • #dispatch_count ENTRYPOINT N for dispatching an entrypoint multiple times in a row
  • #storage NAME TYPE for declaring a storage buffer


Read-write storage buffers can be declared using the #storage directive. For example, you can create a buffer of atomic counters:
#storage atomic_storage array<atomic<i32>>
You could use WGSL's built-in functions to do atomic operations on this buffer in any order, enabling you to safely perform work across many threads at once and accumulate the result in one place. Note that any writes to read-write storage buffers are immediately visible to subsequent reads (unlike the situation with pass_in and pass_out).

The final visual output of every shader is written to the screen storage texture, which displays the result in the canvas on this page.

Debugging assertions are supported with an assert helper function:
assert(0, isfinite(col.x))
assert(1, isfinite(col.y))



Every shader begins with a common prelude. The prelude contains the data inputs and outputs for this shader, as well as a few helper functions and type definitions to make working with @compute.toys a more streamlined and familiar process. Please refer to the prelude for a complete listing of the available data in your shader.

Here are the current contents of this shader's prelude:
Note: Matrix types in WGSL are stored in column-major order. This means a matrix of type mat2x3<f32> (aka mat2x3f or float2x3) is constructed from 2 column vectors of type vec3<f32> (aka vec3f or float3). This is backward from HLSL and convention in mathematics.
  • Channel 0 texture
  • Channel 1 texture
  • https://dl.polyhaven.org/file/ph-assets/Textures/jpg/1k/stone_brick_wall_001/stone_brick_wall_001_diff_1k.jpg
  • https://dl.polyhaven.org/file/ph-assets/Textures/jpg/1k/wood_table_001/wood_table_001_diff_1k.jpg
  • https://dl.polyhaven.org/file/ph-assets/Textures/jpg/1k/rusty_metal_02/rusty_metal_02_diff_1k.jpg
  • https://dl.polyhaven.org/file/ph-assets/Textures/jpg/1k/rock_pitted_mossy/rock_pitted_mossy_diff_1k.jpg
  • https://dl.polyhaven.org/file/ph-assets/Textures/jpg/1k/aerial_rocks_02/aerial_rocks_02_diff_1k.jpg
  • https://dl.polyhaven.org/file/ph-assets/Textures/jpg/1k/book_pattern/book_pattern_col2_1k.jpg
  • https://dl.polyhaven.org/file/ph-assets/HDRIs/hdr/2k/autumn_crossing_2k.hdr
  • https://dl.polyhaven.org/file/ph-assets/HDRIs/hdr/2k/dikhololo_night_2k.hdr
  • https://dl.polyhaven.org/file/ph-assets/HDRIs/hdr/2k/leadenhall_market_2k.hdr
  • https://dl.polyhaven.org/file/ph-assets/HDRIs/hdr/2k/music_hall_01_2k.hdr
  • https://dl.polyhaven.org/file/ph-assets/HDRIs/hdr/2k/spruit_sunrise_2k.hdr
  • https://dl.polyhaven.org/file/ph-assets/HDRIs/hdr/2k/vatican_road_2k.hdr
  • /textures/blank.png
  • /textures/london.jpg
  • /textures/anim0.png
  • /textures/bayer0.png
  • /textures/font0.png
  • https://dl.polyhaven.org/file/ph-assets/Textures/jpg/1k/rocks_ground_01/rocks_ground_01_disp_1k.jpg
  • /textures/noise0.png
  • /textures/noise1.png
  • /textures/noise2.png
  • /textures/noise3.png
  • /textures/noise4.png
  • Settings
  • Float32 Buffers