Skip to content

Instantly share code, notes, and snippets.

@greggman
Last active June 24, 2024 22:52
Show Gist options
  • Save greggman/00c3932c4c63abdcf04c3bb1693c190a to your computer and use it in GitHub Desktop.
Save greggman/00c3932c4c63abdcf04c3bb1693c190a to your computer and use it in GitHub Desktop.
WebGPU Inter-Stage Flat Test
/*bug-in-github-api-content-can-not-be-empty*/
/*bug-in-github-api-content-can-not-be-empty*/
async function main() {
const adapter = await navigator.gpu?.requestAdapter({compatibilityMode: true});
console.log('compatibilityMode:', JSON.stringify(adapter.isCompatibilityMode));
const device = await adapter?.requestDevice();
if (!device) {
alert('need a browser that supports WebGPU');
return;
}
const tests = [
{
code: '(f32(vertexIndex) + 0.5) / 6.0 * 2.0 - 1.0, 0.5',
topology: 'point-list',
count: 6,
},
{
code: '(f32(vertexIndex + vertexIndex % 2) + 0.5) / 6.0 * 2.0 - 1.0, 0.5',
topology: 'line-list',
count: 6,
},
{
// 0 0 0 6 6 6
// 0 1 2 0 1 2
// 0 1 2 6 7 8
// 0 1/6 2/6 6/6 7/6 8/6
code: '(f32(vertexIndex / 3 + vertexIndex % 3) / 6.0) * 2.0 - 1.0, -0.1 + f32(vertexIndex % 3 % 2) * 0.2',
topology: 'triangle-list',
count: 3 * 6,
},
];
for (const {code, topology, count} of tests) {
const module = device.createShaderModule({
code: `
struct OurVertexShaderOutput {
@builtin(position) position: vec4f,
@location(0) @interpolate(flat, either) vertexIndex: u32,
};
@vertex fn vs(
@builtin(vertex_index) vertexIndex : u32,
) -> OurVertexShaderOutput {
var vsOutput: OurVertexShaderOutput;
vsOutput.position = vec4f(${code}, 0, 1);
vsOutput.vertexIndex = vertexIndex;
return vsOutput;
}
@fragment fn fs(@location(0) @interpolate(flat, either) vertexIndex: u32) -> @location(0) vec4f {
return vec4f(f32(vertexIndex) / 255.0);
}
`,
});
const pipeline = device.createRenderPipeline({
layout: 'auto',
vertex: {
module,
entryPoint: 'vs',
},
fragment: {
module,
entryPoint: 'fs',
targets: [{ format: 'rgba8unorm' }],
},
primitive: {
topology,
},
});
const renderPassDescriptor = {
label: 'our basic canvas renderPass',
colorAttachments: [
{
// view: <- to be filled out when we render
clearValue: [0.3, 0.3, 0.3, 0.3],
loadOp: 'clear',
storeOp: 'store',
},
],
};
const texture = device.createTexture({
format: 'rgba8unorm',
size: [6, 1],
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
});
renderPassDescriptor.colorAttachments[0].view = texture.createView();
const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass(renderPassDescriptor);
pass.setPipeline(pipeline);
pass.draw(count);
pass.end();
const buffer = device.createBuffer({
size: 6 * 4,
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
});
encoder.copyTextureToBuffer(
{ texture },
{ buffer },
[ 6, 1 ],
);
const commandBuffer = encoder.finish();
device.queue.submit([commandBuffer]);
await buffer.mapAsync(GPUMapMode.READ);
const data = Array.from(new Uint32Array(buffer.getMappedRange())).map(v => v & 0xFF);
console.log(topology, data);
}
}
main();
{"name":"WebGPU Inter-Stage Flat Test","settings":{},"filenames":["index.html","index.css","index.js"]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment