Skip to content

Instantly share code, notes, and snippets.

@greggman
Created November 27, 2025 16:45
Show Gist options
  • Select an option

  • Save greggman/62246b206acd29fb89f4cb1fc66d77b7 to your computer and use it in GitHub Desktop.

Select an option

Save greggman/62246b206acd29fb89f4cb1fc66d77b7 to your computer and use it in GitHub Desktop.
WebGPU: Test DrawIndexed
/*bug-in-github-api-content-can-not-be-empty*/
/*bug-in-github-api-content-can-not-be-empty*/
/**
* @param {GPUDevice} device
*/
async function testDrawCommand(device, fn) {
const dstTexture = device.createTexture({
format: 'rgba8uint',
size: [1],
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC,
});
const module = device.createShaderModule({
code: `
struct VOut {
@builtin(position) pos: vec4f,
@location(0) @interpolate(flat, either) params: vec4u,
};
@vertex fn vs(
@builtin(vertex_index) vNdx: u32,
@builtin(instance_index) iNdx: u32) -> VOut
{
return VOut(
vec4f(0, 0, 0, 1),
vec4u(vNdx, iNdx, 0x33, 0x44));
}
@fragment fn fs(v: VOut) -> @location(0) vec4u {
return v.params;
}
`,
});
const pipeline = device.createRenderPipeline({
layout: 'auto',
vertex: { module },
fragment: { module, targets: [{ format: 'rgba8uint' }] },
primitive: { topology: 'point-list' },
});
const encoder = device.createCommandEncoder();
const pass = encoder.beginRenderPass({
colorAttachments: [
{
view: dstTexture.createView(),
loadOp: 'clear',
storeOp: 'store',
},
],
});
pass.setPipeline(pipeline);
fn(pass);
pass.end();
const result = device.createBuffer({
size: 4,
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,
});
encoder.copyTextureToBuffer(
{ texture: dstTexture },
{ buffer: result },
[1],
);
device.queue.submit([encoder.finish()]);
await result.mapAsync(GPUMapMode.READ);
const data = new Uint8Array(result.getMappedRange()).slice();
result.unmap();
console.log([...data].map(v => v.toString(16).padStart(2, '0')).join(', '));
}
async function main(){
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const indices = new Uint32Array([
10, // vertexCount
11, // instanceCount
12, // firstVertex
13, // firstInstance
]);
const indexBuffer = device.createBuffer({
size: indices.byteLength,
usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.INDEX,
});
device.queue.writeBuffer(indexBuffer, 0, indices);
await testDrawCommand(device, (pass) => {
pass.setIndexBuffer(indexBuffer, 'uint32');
pass.drawIndexed(
1, // indexcount
1, // instanceCount,
2, // firstIndex,
3, // baseVertex,
0x22, // firstInstance
);
});
}
main();
{"name":"WebGPU: Test DrawIndexed","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