<!DOCTYPE html>
<html>
<head>
<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;
}
`;
let resultsFloat32Array;
async function start() {
    const adapter = await navigator.gpu.requestAdapter();
    const device = await adapter.requestDevice();

    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();
    resultsFloat32Array = new Float32Array(resultsArrayBuffer);
    shouldBe("resultsFloat32Array[0]", "2");
    shouldBe("resultsFloat32Array[1]", "4");
    shouldBe("resultsFloat32Array[2]", "6");
    shouldBe("resultsFloat32Array[3]", "8");
    shouldBe("resultsFloat32Array[4]", "5");
    shouldBe("resultsFloat32Array[5]", "6");
    shouldBe("resultsFloat32Array[6]", "7");
    shouldBe("resultsFloat32Array[7]", "8");
    resultsBuffer.unmap();
}
if (window.testRunner)
    testRunner.waitUntilDone();
window.addEventListener("load", function() {
    start().then(function() {
        if (window.testRunner)
            testRunner.notifyDone();
    }, function() {
        if (window.testRunner)
            testRunner.notifyDone();
    });
});
</script>
<script src="../resources/js-test-post.js"></script>
</body>
</html>
