<!DOCTYPE html>
<meta charset="utf-8">
<title>WebGPU Hello Triangles</title>
<meta name="assert" content="WebGPU correctly renders a green canvas.">
<link rel="match" href="buffer-resource-triangles-expected.html">
<p>Pass if square canvas below is completely green.</p>
<canvas width="400" height="400"></canvas>
<script src="js/webgpu-functions.js"></script>
<script>
if (window.testRunner)
    testRunner.waitUntilDone();

const shaderCode = `
#include <metal_stdlib>
    
using namespace metal;

struct VertexInput {
    float4 position [[attribute(0)]];
};

struct Vertex {
    float4 position [[position]];
};

struct VertexArguments {
    device Vertex* v0;
    device Vertex* v1;
    device Vertex* v2;
};

vertex Vertex vertex_main(
    VertexInput input [[stage_in]],
    const device VertexArguments& args0 [[buffer(0)]],
    const device VertexArguments& args1 [[buffer(1)]],
    uint vid [[vertex_id]])
{
    switch (vid)
    {
        case 0:
        case 1:
        case 2: {
            Vertex out;
            out.position = input.position;
            return out;
        }
        case 3: return *args0.v0;
        case 4: return *args0.v1;
        case 5: return *args0.v2;
        case 6: return *args1.v0;
        case 7: return *args1.v1;
        default: return *args1.v2;
    }
}

struct FragmentArguments {
    device float4* color;
};

fragment float4 fragment_main(const device FragmentArguments& args [[buffer(0)]])
{
    return args.color[0];
}
`

const bindingNums = {
    UL: 0,
    UM: 1,
    UR: 2,
    LL: 3,
    LR: 4,
    G: 5
};

function createUniformBufferBindGroupLayout(bindNum, stage = GPUShaderStageBit.VERTEX) {
    return {
        binding: bindNum,
        visibility: stage,
        type: "uniform-buffer"
    };
}

const vertexSize = 4 * 4;
function createAndUploadVerticesBuffer(device) {
    const vertexArray = new Float32Array([
        0, 1, 0, 1,
        -1, -1, 0, 1,
        1, -1, 0, 1
    ]);
    return createBufferWithData(device, { size: vertexArray.byteLength, usage: GPUBufferUsage.VERTEX }, vertexArray.buffer);
}

function createFloat4Buffer(device, a, b, promises) {
    const buffer = device.createBuffer({ size: vertexSize, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE });

    const promise = buffer.mapWriteAsync().then(mapping => {
        const mappedArray = new Float32Array(mapping);
        mappedArray.set([a, b, 0, 1]);
        buffer.unmap();
    });

    promises.push(promise);
    return buffer;
}

function createBufferBinding(buffer) {
    return { buffer: buffer, size: vertexSize };
}

async function test() {
    const device = await getBasicDevice();
    const canvas = document.querySelector("canvas");
    const swapChain = createBasicSwapChain(canvas, device);
    // FIXME: Replace with non-MSL shaders.
    const shaderModule = device.createShaderModule({ code: shaderCode });

    // Create vertex data GPUBuffers.
    const verticesBuffer = createAndUploadVerticesBuffer(device);

    let bufferPromises = [];
    const upperLeft = createFloat4Buffer(device, -1, 1, bufferPromises);
    const upperMiddle = createFloat4Buffer(device, 0, 1, bufferPromises);
    const upperRight = createFloat4Buffer(device, 1, 1, bufferPromises);
    const lowerLeft = createFloat4Buffer(device, -1, -1, bufferPromises);
    const lowerRight = createFloat4Buffer(device, 1, -1, bufferPromises);

    // Color data buffer.
    const green = createFloat4Buffer(device, 0, 1, bufferPromises);

    // Create vertex input state.
    const vertexInput = {
        indexFormat: "uint32",
        vertexBuffers: [{
            stride: vertexSize,
            attributeSet: [{
                format: "float4",
                shaderLocation: 0
            }]
        }]
    };

    // Create buffer GPUBindGroupLayoutBindings.
    const layoutUL = createUniformBufferBindGroupLayout(bindingNums.UL);
    const layoutUM = createUniformBufferBindGroupLayout(bindingNums.UM);
    const layoutUR = createUniformBufferBindGroupLayout(bindingNums.UR);
    const layoutLL = createUniformBufferBindGroupLayout(bindingNums.LL);
    const layoutLR = createUniformBufferBindGroupLayout(bindingNums.LR);
    const layoutG = createUniformBufferBindGroupLayout(bindingNums.G, GPUShaderStageBit.FRAGMENT);

    // GPUBindGroupLayouts
    const leftTriangleBGLayout = device.createBindGroupLayout({ bindings: [layoutUL, layoutUM, layoutLL, layoutG] });
    const rightTriangleBGLayout = device.createBindGroupLayout({ bindings: [layoutUR, layoutUM, layoutLR] });

    // GPUPipelineLayout and GPURenderPipeline
    const pipelineLayout = device.createPipelineLayout({ bindGroupLayouts: [leftTriangleBGLayout, rightTriangleBGLayout] });
    const pipeline = createBasicPipeline(shaderModule, device, null, pipelineLayout, vertexInput, null, "triangle-list");

    // GPUBufferBindings
    const bindingUL = createBufferBinding(upperLeft);
    const bindingUM = createBufferBinding(upperMiddle);
    const bindingUR = createBufferBinding(upperRight);
    const bindingLL = createBufferBinding(lowerLeft);
    const bindingLR = createBufferBinding(lowerRight);
    const bindingG = createBufferBinding(green);
    
    // GPUBindGroupBindings
    const bgBindingUL = { binding: bindingNums.UL, resource: bindingUL };
    const bgBindingUM = { binding: bindingNums.UM, resource: bindingUM };
    const bgBindingUR = { binding: bindingNums.UR, resource: bindingUR };
    const bgBindingLL = { binding: bindingNums.LL, resource: bindingLL };
    const bgBindingLR = { binding: bindingNums.LR, resource: bindingLR };
    const bgBindingG = { binding: bindingNums.G, resource: bindingG };

    // GPUBindGroups
    const leftTriangleBG = device.createBindGroup({ 
        layout: leftTriangleBGLayout, 
        bindings: [bgBindingUL, bgBindingUM, bgBindingLL, bgBindingG] 
    });
    const rightTriangleBG = device.createBindGroup({
        layout: rightTriangleBGLayout,
        bindings: [bgBindingUR, bgBindingUM, bgBindingLR]
    });

    Promise.all(bufferPromises).then(() => {
        const commandEncoder = device.createCommandEncoder();
        const passEncoder = beginBasicRenderPass(swapChain, commandEncoder);
        passEncoder.setPipeline(pipeline);

        // Vertex data for upper triangles.
        passEncoder.setBindGroup(0, leftTriangleBG);
        passEncoder.setBindGroup(1, rightTriangleBG);
        // Lower triangle.
        passEncoder.setVertexBuffers(0, [verticesBuffer], [0]);
        passEncoder.draw(9, 1, 0, 0);

        passEncoder.endPass();
        const queue = device.getQueue();
        queue.submit([commandEncoder.finish()]);
    });
}

test().then(function() {
    if (window.testRunner)
        testRunner.notifyDone();
}, function() {
    if (window.testRunner)
        testRunner.notifyDone();
});
</script>
