minwebgpu

Crates.iominwebgpu
lib.rsminwebgpu
version0.2.0
created_at2024-09-10 07:12:03.543931+00
updated_at2025-08-09 20:18:23.393792+00
descriptionMinimal WebGPU toolkit for modern graphics programming with compute shaders and rendering pipelines
homepagehttps://github.com/Wandalen/cgtools/tree/master/module/min/minwebgpu
repositoryhttps://github.com/Wandalen/cgtools
max_upload_size
id1370123
size188,984
Wandalen (Wandalen)

documentation

https://docs.rs/minwebgpu

README

⚡ minwebgpu

Modern WebGPU wrapper for next-generation web graphics

A safe, ergonomic Rust wrapper around WebGPU for high-performance graphics and compute in the browser. Built for the future of web graphics with compute shader support, modern rendering pipelines, and optimal WebAssembly integration.

✨ Features

🚀 Next-Gen Graphics

  • WebGPU Native - Direct WebGPU API access with Rust safety
  • Compute Shaders - GPU compute for parallel processing
  • Modern Pipelines - Descriptor-based render and compute pipelines
  • Memory Efficient - Optimal memory management and buffer operations

🛠️ Core Capabilities

  • Render Pipelines - Advanced rendering with modern GPU features
  • Compute Pipelines - Parallel computation on the GPU
  • Buffer Management - Type-safe buffer operations and memory handling
  • Texture Support - 2D/3D textures, cube maps, and texture arrays
  • Shader Modules - WGSL shader compilation and validation
  • Command Encoding - Efficient command buffer recording

🚀 Quick Start

Add to Your Project

[dependencies]
minwebgpu = { workspace = true, features = ["enabled"] }
wasm-bindgen = "0.2"
web-sys = "0.3"

Basic Setup

use minwebgpu as gpu;
use wasm_bindgen::prelude::*;

#[wasm_bindgen(start)]
pub async fn main() -> Result<(), JsValue> {
  // Get WebGPU adapter and device
  let instance = gpu::Instance::new()?;
  let adapter = instance.request_adapter().await?;
  let device = adapter.request_device().await?;
  
  // Create canvas and surface
  let canvas = gpu::canvas::make()?;
  let surface = instance.create_surface(&canvas)?;
  
  Ok(())
}

Simple Triangle Render Pipeline

use minwebgpu as gpu;

// WGSL vertex shader
let vertex_shader = r#"
@vertex
fn vs_main(@location(0) position: vec2<f32>) -> @builtin(position) vec4<f32> {
    return vec4<f32>(position, 0.0, 1.0);
}
"#;

// WGSL fragment shader  
let fragment_shader = r#"
@fragment
fn fs_main() -> @location(0) vec4<f32> {
    return vec4<f32>(1.0, 0.0, 0.0, 1.0);
}
"#;

// Create shader modules
let vs_module = gpu::shader::create(&device, vertex_shader);
let fs_module = gpu::shader::create(&device, fragment_shader);

// Create render pipeline
let pipeline = gpu::render_pipeline::desc(
    gpu::VertexState::new(&vs_module)
        .buffer(&vertex_layout)
)
.fragment(
    gpu::FragmentState::new(&fs_module)
        .target(gpu::ColorTargetState::new().format(surface_format))
)
.primitive(gpu::PrimitiveState::new().triangle_list())
.create(&device)?;

Compute Shader Example

use minwebgpu as gpu;

// WGSL compute shader
let compute_shader = r#"
@group(0) @binding(0) var<storage, read_write> data: array<f32>;

@compute @workgroup_size(64)
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
    let index = global_id.x;
    if (index >= arrayLength(&data)) { return; }
    
    data[index] = data[index] * 2.0;
}
"#;

// Create compute pipeline
let compute_module = gpu::shader::create(&device, compute_shader);
let compute_pipeline = gpu::compute_pipeline::desc(
  gpu::ComputeState::new(&compute_module)
).create(&device)?;

// Create storage buffer
let buffer = gpu::BufferInitDescriptor::new(
    &input_data,
    gpu::BufferUsage::STORAGE | gpu::BufferUsage::COPY_SRC
).create(&device)?;

// Dispatch compute work
let mut encoder = device.create_command_encoder();
let mut compute_pass = encoder.begin_compute_pass();
compute_pass.set_pipeline(&compute_pipeline);
compute_pass.set_bind_group(0, &bind_group);
compute_pass.dispatch_workgroups(workgroup_count, 1, 1);
compute_pass.end();

📚 API Overview

Module Description Key Types
instance WebGPU instance and adapter Instance, Adapter
device Device and queue management Device, Queue
shader WGSL shader compilation ShaderModule, create()
buffer Buffer operations Buffer, BufferInitDescriptor
texture Texture management Texture, TextureView, Sampler
render_pipeline Render pipeline creation RenderPipeline, desc()
compute_pipeline Compute pipeline creation ComputePipeline, desc()
command Command encoding CommandEncoder, RenderPass, ComputePass

🎯 Key Concepts

Render Pipelines

WebGPU uses descriptor-based pipeline creation:

let pipeline = gpu::render_pipeline::desc(
  gpu::VertexState::new(&vs_module)
    .buffer(&vertex_buffer_layout)
)
.fragment(
  gpu::FragmentState::new(&fs_module)
    .target(gpu::ColorTargetState::new().format(gpu::TextureFormat::Bgra8unormSrgb))
)
.primitive(gpu::PrimitiveState::new().triangle_list())
.depth_stencil(gpu::DepthStencilState::new())
.multisample(gpu::MultisampleState::new().count(4))
.create(&device)?;

Buffer Management

Type-safe buffer operations:

// Vertex buffer
let vertices: [Vertex; 3] = [...];
let vertex_buffer = gpu::BufferInitDescriptor::new(
  &vertices,
  gpu::BufferUsage::VERTEX
).create(&device)?;

// Uniform buffer
let uniforms = UniformData { ... };
let uniform_buffer = gpu::BufferInitDescriptor::new(
  &uniforms,
  gpu::BufferUsage::UNIFORM | gpu::BufferUsage::COPY_DST
).create(&device)?;

Bind Groups

Resource binding for shaders:

let bind_group_layout = device.create_bind_group_layout(&gpu::BindGroupLayoutDescriptor {
  entries: &[
    gpu::BindGroupLayoutEntry::uniform(0, gpu::ShaderStage::VERTEX),
    gpu::BindGroupLayoutEntry::texture(1, gpu::ShaderStage::FRAGMENT),
    gpu::BindGroupLayoutEntry::sampler(2, gpu::ShaderStage::FRAGMENT),
  ],
});

let bind_group = device.create_bind_group(&gpu::BindGroupDescriptor {
  layout: &bind_group_layout,
  entries: &[
    gpu::BindGroupEntry::buffer(0, &uniform_buffer),
    gpu::BindGroupEntry::texture_view(1, &texture_view),
    gpu::BindGroupEntry::sampler(2, &sampler),
  ],
});

🎮 Examples

🔧 Advanced Features

Compute Shaders

// Parallel array processing
let compute_pipeline = gpu::compute_pipeline::desc(
  gpu::ComputeState::new(&compute_module)
).create(&device)?;

// Dispatch with workgroups
compute_pass.dispatch_workgroups(
  (data_size + 63) / 64, // Round up to workgroup size
  1,
  1
);

Multi-Target Rendering

let pipeline = gpu::render_pipeline::desc(vertex_state)
.fragment(
  gpu::FragmentState::new(&fs_module)
    .target(gpu::ColorTargetState::new().format(gpu::TextureFormat::Rgba8unorm))
    .target(gpu::ColorTargetState::new().format(gpu::TextureFormat::Rgba16Float))
)
.create(&device)?;

Memory-Mapped Buffers

// Create mappable buffer
let buffer = device.create_buffer(&gpu::BufferDescriptor {
  size: data.len() as u64,
  usage: gpu::BufferUsage::MAP_READ | gpu::BufferUsage::COPY_DST,
  mapped_at_creation: false,
});

// Map and read data
let buffer_slice = buffer.slice(..);
buffer_slice.map_async(gpu::MapMode::Read).await?;
let data = buffer_slice.get_mapped_range();
// Process data...
buffer.unmap();

🛠️ Building

WebGPU requires modern browser support:

Browser Requirements

  • Chrome/Edge: Version 94+
  • Firefox: Version 110+ (behind flag)
  • Safari: Version 16.4+

Build Commands

# Build for web
wasm-pack build --target web --out-dir pkg

# Development with trunk
trunk serve --release

🤝 Contributing

Part of the CGTools workspace. Feel free to submit issues and pull requests on GitHub.

📄 License

MIT

Commit count: 696

cargo fmt