<!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;
const verticesBufferSize = vertexSize * 3;
function createAndUploadVerticesBuffer(device) {
    const buffer = device.createBuffer({ size:verticesBufferSize, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST });
    const arrayBuffer = new Float32Array([
        0, 1, 0, 1,
        -1, -1, 0, 1,
        1, -1, 0, 1
    ]).buffer;

    buffer.setSubData(0, arrayBuffer);
    return 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 inputState = {
        indexFormat: "uint32",
        attributes: [{
            shaderLocation: 0,
            inputSlot: 0,
            format: "float4"
        }],
        inputs: [{
            inputSlot: 0,
            stride: vertexSize
        }]
    };

    // 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, inputState, 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()]);

        if (window.testRunner)
            testRunner.notifyDone();
    });
}

test();
</script>