<!DOCTYPE html>
<html>
<head>
<script src="../js/webgpu-functions.js"></script>
<script src="../../resources/js-test-pre.js"></script>
</head>
<body>
<script>
const shaderSource = `
bool allEqual(float4x4 mat, float value)
{
    for (uint i = 0; i < 4; i = i + 1) {
        for (uint j = 0; j < 4; j = j + 1) {
            if (mat[i][j] != value)
                return false;
        }
    }
    return true;
}

bool fill(thread float4x4* mat, float value)
{
    float4x4 result;
    for (uint i = 0; i < 4; i = i + 1) {
            result[i] = float4(value, value, value, value);
    }
    *mat = result;
    return true;
}

bool fill(thread float4* vec, float value)
{
    float4 result;
    for (uint i = 0; i < 4; i = i + 1) {
        result[i] = value;
    }
    *vec = result;
    return true;
}

bool allEqual(float4 vec, float value)
{
    for (uint i = 0; i < 4; i = i + 1) {
        if (vec[i] != value)
            return false;
    }
    return true;
}

[numthreads(1, 1, 1)]
compute void computeShader(device float[] buffer : register(u0), float3 threadID : SV_DispatchThreadID) {
    float4x4 mat;
    fill(&mat, 1);
    if (!allEqual(mat, 1))
        return;

    float4 vec;
    fill(&vec, 1);
    if (!allEqual(vec, 1))
        return;

    float4 vec2 = mul(mat, vec);
    if (!allEqual(vec2, 4))
        return;

    float4x4 mat2 = mul(mat, mat);
    if (!allEqual(mat2, 4))
        return;

    mat2 = mul(mat2, mat2);
    if (!allEqual(mat2, 64))
        return;

    buffer[uint(threadID.x)] = buffer[uint(threadID.x)] * 2.0;
}
`;

async function start(device) {
    const shaderModule = device.createShaderModule({code: shaderSource});
    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 * 8;

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

    const resultsBufferDescriptor = {size, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_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(4, 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] == 2
        && resultsFloat32Array[1] == 4
        && resultsFloat32Array[2] == 6
        && resultsFloat32Array[3] == 8
        && resultsFloat32Array[4] == 5
        && resultsFloat32Array[5] == 6
        && resultsFloat32Array[6] == 7
        && resultsFloat32Array[7] == 8)
        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>
