Skip to content

Instantly share code, notes, and snippets.

@greggman
Last active July 25, 2025 19:23
Show Gist options
  • Save greggman/d1f2f12514cd479bf32af9c5ede130c7 to your computer and use it in GitHub Desktop.
Save greggman/d1f2f12514cd479bf32af9c5ede130c7 to your computer and use it in GitHub Desktop.
WebGPU: Test textureGatherCompare with swizzle
/*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();
if (!adapter.features.has('texture-component-swizzle')) {
console.error('need texture-component-swizzle');
}
const device = await adapter.requestDevice({
requiredFeatures: ['texture-component-swizzle'],
});
device.addEventListener('uncapturederror', e => console.error(e.error.message));
const pipeline = device.createComputePipeline({
layout: 'auto',
compute: {
module: device.createShaderModule({
code: `
@group(0) @binding(0) var<storage, read_write> result: array<vec4f>;
@group(0) @binding(1) var tex: texture_depth_2d;
@group(0) @binding(2) var smp: sampler_comparison;
@compute @workgroup_size(1) fn main(
@builtin(global_invocation_id) id: vec3<u32>) {
result[id.x] = textureGatherCompare(tex, smp, vec2f(0.5), 0.5);
}
`,
}),
entryPoint: 'main',
},
});
const texels = [ // for gather this is will be
0.2, 0.4, // a b
0.6, 0.8, // r g
];
console.log('texels:', texels.join(', '));
console.log('gather: a b g r');
const texture = device.createTexture({
format: 'depth16unorm',
size: [2, 2],
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
});
device.queue.writeTexture(
{ texture },
new Uint16Array(texels.map(v => Math.round(65535 * v))),
{
bytesPerRow: 4,
},
[2, 2]
);
const buffer = device.createBuffer({
size: 4 * 4,
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
});
const resultBuffer = device.createBuffer({
size: buffer.size,
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
});
const tests = [
{ swizzle: { }},
{ swizzle: { r: 'one', b: 'one', g: 'one', a: 'one' }},
{ swizzle: { r: 'zero', b: 'zero', g: 'zero', a: 'zero' }},
{ swizzle: { r: 'a', b: 'g', g: 'b', a: 'r' }},
{ swizzle: { r: 'r', b: 'r', g: 'r', a: 'r' }},
];
for (const compare of ['less', 'greater']) {
console.log('\ncompare:', compare, ', ref: 0.5');
const sampler = device.createSampler({
compare,
});
for (const { swizzle } of tests) {
const bindGroup = device.createBindGroup({
layout: pipeline.getBindGroupLayout(0),
entries: [
{ binding: 0, resource: { buffer } },
{ binding: 1, resource: texture.createView({ swizzle }) },
{ binding: 2, resource: sampler },
],
});
const encoder = device.createCommandEncoder();
const pass = encoder.beginComputePass();
pass.setPipeline(pipeline);
pass.setBindGroup(0, bindGroup);
pass.dispatchWorkgroups(1);
pass.end();
encoder.copyBufferToBuffer(buffer, 0, resultBuffer, 0, resultBuffer.size);
device.queue.submit([encoder.finish()]);
await resultBuffer.mapAsync(GPUMapMode.READ);
const results = Array.from(new Float32Array(resultBuffer.getMappedRange()));
resultBuffer.unmap();
console.log(results, 'swizzle:', JSON.stringify(swizzle).replace(/"(.*?)"\:"(.*?)"/g, "$1:'$2'"));
}
}
}
main();
{"name":"WebGPU: Test textureGatherCompare with swizzle","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