<!DOCTYPE html>
<html>
<head>
<script src="js/webgpu-functions.js"></script>
<script src="../resources/js-test-pre.js"></script>
</head>
<body>
<script>
const shaderSource = `
[numthreads(1, 1, 1)]
compute void computeShader(device float4x4[] buffer : register(u0), float3 threadID : SV_DispatchThreadID) {
    float4x4 result;
    result[0] = float4(1, 2, 3, 4);
    result[1] = float4(5, 6, 7, 8);
    result[2] = float4(9, 10, 11, 12);
    result[3] = float4(13, 14, 15, 16);

    float4x4 mat = buffer[0];

    if (mat[0][0] == 0
        && mat[0][1] == 1
        && mat[0][2] == 2
        && mat[0][3] == 3

        && mat[1][0] == 4
        && mat[1][1] == 5
        && mat[1][2] == 6
        && mat[1][3] == 7

        && mat[2][0] == 8
        && mat[2][1] == 9
        && mat[2][2] == 10
        && mat[2][3] == 11

        && mat[3][0] == 12
        && mat[3][1] == 13
        && mat[3][2] == 14
        && mat[3][3] == 15) {
        buffer[0] = result;
    }
}
`;

async function start(device) {
    const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true});
    const computeStage = {module: shaderModule, entryPoint: "computeShader"};

    const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "storage-buffer"}]};
    const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor);
    const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]};
    const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor);

    const computePipelineDescriptor = {computeStage, layout: pipelineLayout};
    const computePipeline = device.createComputePipeline(computePipelineDescriptor);

    const size = Float32Array.BYTES_PER_ELEMENT * 16;

    const bufferDescriptor = {size, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.TRANSFER_SRC};
    const buffer = device.createBuffer(bufferDescriptor);
    const bufferArrayBuffer = await buffer.mapWriteAsync();
    const bufferFloat32Array = new Float32Array(bufferArrayBuffer);
    bufferFloat32Array[0] = 0;
    bufferFloat32Array[1] = 4;
    bufferFloat32Array[2] = 8;
    bufferFloat32Array[3] = 12;
    bufferFloat32Array[4] = 1;
    bufferFloat32Array[5] = 5;
    bufferFloat32Array[6] = 9;
    bufferFloat32Array[7] = 13;
    bufferFloat32Array[8] = 2;
    bufferFloat32Array[9] = 6;
    bufferFloat32Array[10] = 10;
    bufferFloat32Array[11] = 14;
    bufferFloat32Array[12] = 3;
    bufferFloat32Array[13] = 7;
    bufferFloat32Array[14] = 11;
    bufferFloat32Array[15] = 15;
    buffer.unmap();

    const resultsBufferDescriptor = {size, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.TRANSFER_DST | GPUBufferUsage.MAP_READ};
    const resultsBuffer = device.createBuffer(resultsBufferDescriptor);

    const bufferBinding = {buffer: resultsBuffer, size};
    const bindGroupBinding = {binding: 0, resource: bufferBinding};
    const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]};
    const bindGroup = device.createBindGroup(bindGroupDescriptor);

    const commandEncoder = device.createCommandEncoder(); // {}
    commandEncoder.copyBufferToBuffer(buffer, 0, resultsBuffer, 0, size);
    const computePassEncoder = commandEncoder.beginComputePass();
    computePassEncoder.setPipeline(computePipeline);
    computePassEncoder.setBindGroup(0, bindGroup);
    computePassEncoder.dispatch(2, 1, 1);
    computePassEncoder.endPass();
    const commandBuffer = commandEncoder.finish();
    device.getQueue().submit([commandBuffer]);

    const resultsArrayBuffer = await resultsBuffer.mapReadAsync();
    const resultsFloat32Array = new Float32Array(resultsArrayBuffer);
    if (resultsFloat32Array[0] === 1
        && resultsFloat32Array[1] === 5
        && resultsFloat32Array[2] === 9
        && resultsFloat32Array[3] === 13

        && resultsFloat32Array[4] === 2
        && resultsFloat32Array[5] === 6
        && resultsFloat32Array[6] === 10
        && resultsFloat32Array[7] === 14

        && resultsFloat32Array[8] === 3
        && resultsFloat32Array[9] === 7
        && resultsFloat32Array[10] === 11
        && resultsFloat32Array[11] === 15

        && resultsFloat32Array[12] === 4
        && resultsFloat32Array[13] === 8
        && resultsFloat32Array[14] === 12
        && resultsFloat32Array[15] === 16)
        testPassed("");
    else
        testFailed("");
    resultsBuffer.unmap();
}
window.jsTestIsAsync = true;
getBasicDevice().then(function(device) {
    start(device).then(function() {
        finishJSTest();
    }, function() {
        testFailed("");
        finishJSTest();
    });
}, function() {
    testPassed("");
    finishJSTest();
});
</script>
<script src="../resources/js-test-post.js"></script>
</body>
</html>
