Contents

1amageek/swift-webgpu

Type-safe Swift bindings for the [WebGPU API](https://www.w3.org/TR/webgpu/), enabling GPU-accelerated graphics and compute in WebAssembly applications.

Overview

SwiftWebGPU provides idiomatic Swift wrappers for the WebGPU API, allowing you to write GPU-accelerated code in Swift that runs in the browser via WebAssembly.

Architecture: Swift (WASM) → JavaScriptKit → JavaScript → WebGPU API

Requirements

  • Swift 6.0+
  • SwiftWasm toolchain for WebAssembly compilation
  • A browser with WebGPU support (Chrome 113+, Edge 113+, Firefox 114+ with flag)

Installation

Add SwiftWebGPU to your Package.swift:

dependencies: [
    .package(url: "https://github.com/1amageek/swift-webgpu.git", from: "0.1.0")
]

Then add it to your target dependencies:

.target(
    name: "YourTarget",
    dependencies: [
        .product(name: "SwiftWebGPU", package: "swift-webgpu")
    ]
)

Usage

Getting Started

import SwiftWebGPU

// Check WebGPU availability
guard let gpu = GPU.shared else {
    print("WebGPU is not supported")
    return
}

// Request an adapter and device
let adapter = try await gpu.requestAdapter()
let device = try await adapter?.requestDevice()

Creating a Buffer

let buffer = device.createBuffer(descriptor: GPUBufferDescriptor(
    size: 256,
    usage: [.vertex, .copyDst]
))

Creating a Shader Module

let shaderModule = device.createShaderModule(descriptor: GPUShaderModuleDescriptor(
    code: """
    @vertex
    fn vs_main(@builtin(vertex_index) idx: u32) -> @builtin(position) vec4f {
        var positions = array<vec2f, 3>(
            vec2f(0.0, 0.5),
            vec2f(-0.5, -0.5),
            vec2f(0.5, -0.5)
        );
        return vec4f(positions[idx], 0.0, 1.0);
    }

    @fragment
    fn fs_main() -> @location(0) vec4f {
        return vec4f(1.0, 0.0, 0.0, 1.0);
    }
    """
))

Creating a Render Pipeline

let pipeline = device.createRenderPipeline(descriptor: GPURenderPipelineDescriptor(
    vertex: GPUVertexState(
        module: shaderModule,
        entryPoint: "vs_main"
    ),
    fragment: GPUFragmentState(
        module: shaderModule,
        entryPoint: "fs_main",
        targets: [
            GPUColorTargetState(format: gpu.preferredCanvasFormat)
        ]
    )
))

Rendering

// Get the canvas context
let canvas = JSObject.global.document.getElementById!("canvas").object!
let context = GPUCanvasContext(jsObject: canvas.getContext!("webgpu").object!)

context.configure(GPUCanvasConfiguration(
    device: device,
    format: gpu.preferredCanvasFormat
))

// Create command encoder and render
let encoder = device.createCommandEncoder()
let renderPass = encoder.beginRenderPass(descriptor: GPURenderPassDescriptor(
    colorAttachments: [
        GPURenderPassColorAttachment(
            view: context.getCurrentTexture().createView(),
            loadOp: .clear,
            storeOp: .store,
            clearValue: GPUColor(r: 0.0, g: 0.0, b: 0.0, a: 1.0)
        )
    ]
))

renderPass.setPipeline(pipeline)
renderPass.draw(3)
renderPass.end()

device.queue.submit([encoder.finish()])

API Overview

Core Classes

| Class | Description | |-------|-------------| | GPU | Entry point via navigator.gpu | | GPUAdapter | Represents a GPU adapter | | GPUDevice | Main interface for creating GPU resources | | GPUBuffer | GPU buffer for vertex/index/uniform data | | GPUTexture | GPU texture resource | | GPUShaderModule | Compiled shader module | | GPURenderPipeline | Render pipeline configuration | | GPUComputePipeline | Compute pipeline configuration | | GPUCommandEncoder | Records GPU commands | | GPURenderPassEncoder | Encodes render pass commands | | GPUComputePassEncoder | Encodes compute pass commands | | GPUQueue | Command submission queue | | GPUBindGroup | Resource bindings for shaders | | GPUCanvasContext | Canvas rendering context |

Enums

All WebGPU enums are represented as Swift enums with String raw values matching the WebGPU specification:

public enum GPUTextureFormat: String, Sendable {
    case rgba8unorm = "rgba8unorm"
    case bgra8unorm = "bgra8unorm"
    case depth24plus = "depth24plus"
    // ...
}

Flags

WebGPU flags are represented as OptionSet types:

public struct GPUBufferUsage: OptionSet, Sendable {
    public static let mapRead = GPUBufferUsage(rawValue: 0x0001)
    public static let mapWrite = GPUBufferUsage(rawValue: 0x0002)
    public static let copyDst = GPUBufferUsage(rawValue: 0x0008)
    public static let vertex = GPUBufferUsage(rawValue: 0x0020)
    public static let uniform = GPUBufferUsage(rawValue: 0x0040)
    // ...
}

// Usage
let usage: GPUBufferUsage = [.vertex, .copyDst]

Building for WebAssembly

# Build for WASM (requires SwiftWasm toolchain)
swift build --triple wasm32-unknown-wasi

References

License

MIT License

Package Metadata

Repository: 1amageek/swift-webgpu

Stars: 3

Forks: 0

Open issues: 0

Default branch: main

Primary language: swift

README: README.md