blob: 807294ac2f69e8b994fe0c359cbb30df42551918 [file] [edit]
<script src="../../resources/js-test.js"></script>
<script>
jsTestIsAsync = true;
// Integer texels, so that what comes back can be compared exactly.
const shaderCode = `
@group(0) @binding(0) var sourceTexture: texture_2d<u32>;
@group(0) @binding(1) var<storage, read_write> result: array<u32, 4>;
@compute @workgroup_size(1)
fn main()
{
let texel = textureLoad(sourceTexture, vec2u(0, 0), 0);
result[0] = texel.r;
result[1] = texel.g;
result[2] = texel.b;
result[3] = texel.a;
}
`;
onload = async () => {
const adapter = await navigator.gpu.requestAdapter({});
const device = await adapter.requestDevice({ requiredFeatures: ['texture-component-swizzle'] });
const texture = device.createTexture({
size: [1, 1],
format: 'rgba8uint',
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,
});
device.queue.writeTexture({ texture }, new Uint8Array([11, 22, 33, 44]), { bytesPerRow: 4 }, [1, 1]);
const bindGroupLayout = device.createBindGroupLayout({
entries: [
{ binding: 0, visibility: GPUShaderStage.COMPUTE, texture: { sampleType: 'uint' } },
{ binding: 1, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } },
],
});
const pipeline = device.createComputePipeline({
layout: device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] }),
compute: { module: device.createShaderModule({ code: shaderCode }) },
});
async function readThroughSwizzle(swizzle)
{
const storageBuffer = device.createBuffer({ size: 16, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC });
const readbackBuffer = device.createBuffer({ size: 16, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ });
const bindGroup = device.createBindGroup({
layout: bindGroupLayout,
entries: [
{ binding: 0, resource: texture.createView({ swizzle }) },
{ binding: 1, resource: { buffer: storageBuffer } },
],
});
const commandEncoder = device.createCommandEncoder();
const computePass = commandEncoder.beginComputePass({});
computePass.setPipeline(pipeline);
computePass.setBindGroup(0, bindGroup);
computePass.dispatchWorkgroups(1);
computePass.end();
commandEncoder.copyBufferToBuffer(storageBuffer, 0, readbackBuffer, 0, 16);
device.queue.submit([commandEncoder.finish()]);
await readbackBuffer.mapAsync(GPUMapMode.READ);
const values = [...new Uint32Array(readbackBuffer.getMappedRange())].toString();
readbackBuffer.unmap();
return values;
}
globalThis.identity = await readThroughSwizzle('rgba');
shouldBeEqualToString('identity', '11,22,33,44');
globalThis.reversed = await readThroughSwizzle('abgr');
shouldBeEqualToString('reversed', '44,33,22,11');
globalThis.broadcast = await readThroughSwizzle('gggg');
shouldBeEqualToString('broadcast', '22,22,22,22');
// '0' and '1' force the channel rather than selecting one.
globalThis.constants = await readThroughSwizzle('01ab');
shouldBeEqualToString('constants', '0,1,44,33');
finishJSTest();
};
</script>