A WebGPU implementation based on the excellent wgpu crate.

Overview

node-wgpu

A WebGPU implementation based on the excellent wgpu crate.

Work in progress. Just far along enough to execute the following snippet:

[[builtin(position)]] vec4 { let x = f32(i32(in_vertex_index) - 1); let y = f32(i32(in_vertex_index & 1u) * 2 - 1); return vec4(x, y, 0.0, 1.0); } [[stage(fragment)]] fn fs_main() -> [[location(0)]] vec4 { return vec4(1.0, 0.0, 0.0, 1.0); } ` const shaderModule = device.createShaderModule({ code: shaderCode }) const pipelineLayout = device.createPipelineLayout({ bindGroupLayouts: [], }) const renderPipeline = device.createRenderPipeline({ layout: pipelineLayout, vertex: { module: shaderModule, entryPoint: "vs_main", }, fragment: { module: shaderModule, entryPoint: "fs_main", targets: [ { format: "rgba8unorm-srgb" }, ], }, }) const { texture, outputBuffer } = createCapture(device, dimensions) const encoder = device.createCommandEncoder() const renderPass = encoder.beginRenderPass({ colorAttachments: [{ view: texture.createView(), storeOp: "store", loadValue: [0, 1, 0, 1], }], }) renderPass.setPipeline(renderPipeline) renderPass.draw(3, 1) renderPass.end() function createCapture(device, dimensions) { const { padded } = getRowPadding(dimensions.width) const outputBuffer = device.createBuffer({ label: "Capture", size: padded * dimensions.height, usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST, }) const texture = device.createTexture({ label: "Capture", size: dimensions, format: "rgba8unorm-srgb", usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC, }) return { outputBuffer, texture } } function getRowPadding(width) { // It is a webgpu requirement that BufferCopyView.layout.bytes_per_row % COPY_BYTES_PER_ROW_ALIGNMENT(256) == 0 // So we calculate padded_bytes_per_row by rounding unpadded_bytes_per_row // up to the next multiple of COPY_BYTES_PER_ROW_ALIGNMENT. // https://en.wikipedia.org/wiki/Data_structure_alignment#Computing_padding const bytesPerPixel = 4 const unpaddedBytesPerRow = width * bytesPerPixel const align = 256 const paddedBytesPerRowPadding = (align - unpaddedBytesPerRow % align) % align const paddedBytesPerRow = unpaddedBytesPerRow + paddedBytesPerRowPadding return { unpadded: unpaddedBytesPerRow, padded: paddedBytesPerRow, } }">
// Adapted from https://github.com/denoland/webgpu-examples/blob/main/hello-triangle/mod.ts
import gpu from "gpu"

const {
    GPUBufferUsage,
    GPUTextureUsage,
} = gpu

const adapter = await gpu.requestAdapter()
const device = await adapter?.requestDevice()

const shaderCode = `
    [[stage(vertex)]]
    fn vs_main([[builtin(vertex_index)]] in_vertex_index: u32) -> [[builtin(position)]] vec4 {
        let x = f32(i32(in_vertex_index) - 1);
        let y = f32(i32(in_vertex_index & 1u) * 2 - 1);
        return vec4(x, y, 0.0, 1.0);
    }

    [[stage(fragment)]]
    fn fs_main() -> [[location(0)]] vec4 {
        return vec4(1.0, 0.0, 0.0, 1.0);
    }
`

const shaderModule = device.createShaderModule({ code: shaderCode })

const pipelineLayout = device.createPipelineLayout({
    bindGroupLayouts: [],
})

const renderPipeline = device.createRenderPipeline({
    layout: pipelineLayout,
    vertex: {
        module: shaderModule,
        entryPoint: "vs_main",
    },
    fragment: {
        module: shaderModule,
        entryPoint: "fs_main",
        targets: [
            { format: "rgba8unorm-srgb" },
        ],
    },
})

const { texture, outputBuffer } = createCapture(device, dimensions)

const encoder = device.createCommandEncoder()

const renderPass = encoder.beginRenderPass({
    colorAttachments: [{
        view: texture.createView(),
        storeOp: "store",
        loadValue: [0, 1, 0, 1],
    }],
})
renderPass.setPipeline(renderPipeline)
renderPass.draw(3, 1)
renderPass.end()

function createCapture(device, dimensions) {
    const { padded } = getRowPadding(dimensions.width)
    const outputBuffer = device.createBuffer({
        label: "Capture",
        size: padded * dimensions.height,
        usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
    })
    const texture = device.createTexture({
        label: "Capture",
        size: dimensions,
        format: "rgba8unorm-srgb",
        usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
    })
    return { outputBuffer, texture }
}

function getRowPadding(width) {
    // It is a webgpu requirement that BufferCopyView.layout.bytes_per_row % COPY_BYTES_PER_ROW_ALIGNMENT(256) == 0
    // So we calculate padded_bytes_per_row by rounding unpadded_bytes_per_row
    // up to the next multiple of COPY_BYTES_PER_ROW_ALIGNMENT.
    // https://en.wikipedia.org/wiki/Data_structure_alignment#Computing_padding
    const bytesPerPixel = 4
    const unpaddedBytesPerRow = width * bytesPerPixel
    const align = 256
    const paddedBytesPerRowPadding = (align - unpaddedBytesPerRow % align) % align
    const paddedBytesPerRow = unpaddedBytesPerRow + paddedBytesPerRowPadding

    return {
        unpadded: unpaddedBytesPerRow,
        padded: paddedBytesPerRow,
    }
}
You might also like...
A GUI frontend in Rust based on web-view
A GUI frontend in Rust based on web-view

neutrino I am not working anymore on this project. If you want to become a maintainer of neutrino, please answer to this issue. Preamble Docs | Repo |

JLM: A research compiler based on the RVSDG IR

JLM: A research compiler based on the RVSDG IR Jlm is an experimental compiler/optimizer that consumes and produces LLVM IR. It uses the Regionalized

Based on the Book Computer Graphics from Scratch
Based on the Book Computer Graphics from Scratch

raytracing_basic v1 Description Based on the Book Computer Graphics from Scratch Dependencies Good Web Game Build and run cargo build --release

🪪 Session-based user authentication for Axum.

axum-login 🪪 Session-based user authentication for Axum. 🎨 Overview axum-login is a Tower middleware providing session-based user authentication for

Layers, extractors and template engine wrappers for axum based Web MVC applications

axum-template Layers, extractors and template engine wrappers for axum based Web MVC applications Getting started Cargo.toml [dependencies] axum-templ

HTTP Proxy based solution for real-time interception and prioritization of SQL queries.
HTTP Proxy based solution for real-time interception and prioritization of SQL queries.

starproxy ⚠️ starproxy is a prototype: Not currently used in production, but will likely be some day. Table of Contents starproxy Table of Contents Ba

OpenAPI-based test coverage analysis tool that helps teams improve integration test coverage in CI/CD pipelines
OpenAPI-based test coverage analysis tool that helps teams improve integration test coverage in CI/CD pipelines

Ready-to-use OpenAPI test coverage analysis tool that helps teams improve integration CoveAPI is an advanced test coverage analysis tool based on the

axum-serde is a library that provides multiple serde-based extractors and responders for the Axum web framework.

axum-serde 📑 Overview axum-serde is a library that provides multiple serde-based extractors / responses for the Axum web framework. It also offers a

puppy is an example implementation of a tiny Web browser for educational purposes.
puppy is an example implementation of a tiny Web browser for educational purposes.

An example implementation of a tiny Web browser for educational purposes.

Owner
Ben Noordhuis
Ben Noordhuis
A crate built on top of `axum-sessions`, implementing the CSRF Synchronizer Token Pattern

Axum Synchronizer Token Pattern CSRF prevention This crate provides a Cross-Site Request Forgery protection layer and middleware for use with the axum

null 3 Dec 15, 2022
A Rust crate for managing authentication and authorization with support for multi-tenant / B2B products, powered by PropelAuth

PropelAuth Add authentication and authorization to your application. This library is meant to be used with a PropelAuth account. You can sign up and g

PropelAuth 3 Dec 10, 2022
Download .crate files of all versions of all crates from crates.io

get-all-crates Download .crate files of all versions of all crates from crates.io. Useful for things like noisy-clippy which need to analyze the sourc

David Tolnay 18 Jan 3, 2023
Rate Limiting middleware for Tower/Axum/Tonic/Hyper utilizing the governor crate

A Tower service and layer that provides a rate-limiting backend by governor. Based heavily on the work done for actix-governor. Works with Axum, Hyper

Ben Wishovich 31 Feb 15, 2023
Rust Macros to automate the addition of Paths/Schemas to Utoipa crate, simulating Reflection during the compilation phase

utoipa_auto_discovery Rust Macros to automate the addition of Paths/Schemas to Utoipa crate, simulating Reflection during the compilation phase Crate

null 4 Jun 9, 2023
Murasaki is a Fast, Secure, and Reliable Webkit based web browser.

Murasaki is a Fast, Secure, and Reliable Webkit based web browser. Table of Contents Goals Status Usage License Goals Security: Be secure, and not com

Moon Laboratories 5 Nov 17, 2021
A Blog & RSS system written in Rust based on Luke Smith's LB.

OB - Oliver's Blog Script A Blog and RSS system written in Rust. Features Converts blog entries written in Markdown into HTML. ✍?? Keeps a rolling blo

Oliver Brotchie 19 Aug 28, 2022
A minimal and flexible blog generator based on GitHub Gists.

gisture Utilizing GitHub Gists as a Blogging Platform A minimal and flexible blog generator based on GitHub Gists with SEO, Templating, Syntax Highlig

Mufeed VH 26 Dec 27, 2022
A web application to configuration Caddy based on MoonZoon.

Cream A web application to configuration Caddy based on MoonZoon. MoonZoon is a Rust Fullstack Framework. Live demo Run on a local machine Check you'v

Tw 4 Sep 19, 2022
📝 Web-based, reactive Datalog notebooks for data analysis and visualization

Percival is a declarative data query and visualization language. It provides a reactive, web-based notebook environment for exploring complex datasets, producing interactive graphics, and sharing results.

Eric Zhang 486 Dec 28, 2022