Skip to content

Commit

Permalink
add example
Browse files Browse the repository at this point in the history
  • Loading branch information
greggman committed Jan 6, 2025
1 parent f0d8972 commit 22c55b2
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 0 deletions.
4 changes: 4 additions & 0 deletions example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.pyc
.DS_Store
node_modules
output.png
5 changes: 5 additions & 0 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Example for node-webgpu

* cd to this
* `npm ci`
* `node example.js`
92 changes: 92 additions & 0 deletions example/example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import fs from 'node:fs';
import { PNG } from 'pngjs';
import { create, globals } from 'node-webgpu';

Object.assign(globalThis, globals);
globalThis.navigator = { gpu: create([]) };

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

const module = device.createShaderModule({
code: `
@vertex fn vs(
@builtin(vertex_index) vertexIndex : u32
) -> @builtin(position) vec4f {
let pos = array(
vec2f( 0.0, 0.5),
vec2f(-0.5, -0.5),
vec2f( 0.5, -0.5),
);
return vec4f(pos[vertexIndex], 0.0, 1.0);
}
@fragment fn fs() -> @location(0) vec4f {
return vec4f(1, 0, 0, 1);
}
`,
});

const pipeline = device.createRenderPipeline({
layout: 'auto',
vertex: { module },
fragment: { module, targets: [{ format: 'rgba8unorm' }] },
});

const texture = device.createTexture({
format: 'rgba8unorm',
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
size: [256, 256],
});

const align = (v, alignment) => Math.ceil(v / alignment) * alignment;

const bytesPerRow = align(texture.width * 4, 256);
const buffer = device.createBuffer({
size: bytesPerRow * texture.height,
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
});

const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [
{
view: texture.createView(),
clearValue: [0.3, 0.3, 0.3, 1],
loadOp: 'clear',
storeOp: 'store',
},
],
});
pass.setPipeline(pipeline);
pass.draw(3);
pass.end();
encoder.copyTextureToBuffer(
{ texture },
{ buffer, bytesPerRow },
[ texture.width, texture.height ],
);
const commandBuffer = encoder.finish();
device.queue.submit([commandBuffer]);

await buffer.mapAsync(GPUMapMode.READ);
const rawPixelData = buffer.getMappedRange();

const png = new PNG({
width: texture.width,
height: texture.height,
filterType: -1,
});

const dstBytesPerRow = texture.width * 4;
for (let y = 0; y < texture.height; y++) {
const dst = (texture.width * y) * 4;
const src = (y * bytesPerRow);
png.data.set(new Uint8Array(rawPixelData, src, dstBytesPerRow), dst);
}

// Write the PNG to a file
fs.writeFileSync('output.png', PNG.sync.write(png, {colorType: 6}));
console.log('PNG file has been saved as output.png');
process.exit(0);
30 changes: 30 additions & 0 deletions example/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "example",
"version": "1.0.0",
"description": "example using node-webgpu",
"main": "example.js",
"type": "module",
"scripts": {
"start": "node example.js"
},
"author": "",
"license": "MIT",
"dependencies": {
"node-webgpu": "^0.0.6",
"pngjs": "^7.0.0"
}
}

0 comments on commit 22c55b2

Please sign in to comment.