<!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, 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 * 8;

    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] = 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.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(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>
