<!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="vertex-buffer-triangle-strip-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 = `
struct VertexOut
{
    float4 position : SV_Position;
    float4 color : attribute(0);
};

vertex VertexOut vertex_main(float4 position : attribute(0), uint iid : SV_InstanceID)
{
    VertexOut vOut;
    vOut.position = position;

    if (iid == 0) {
        vOut.position.z = 0.5;
        vOut.color = float4(1, 0, 0, 1);
    } else {
        vOut.color = float4(0, 1, 0, 1);
    }

    return vOut;
}

fragment float4 fragment_main(float4 color : attribute(0)) : SV_Target 0
{
    return color;
}
`

function createVertexBuffer(device) {
    const vertexArray = new Float32Array([
        // float4 xyzw
        -1, 1, 0, 1,
        -1, -1, 0, 1,
        1, 1, 0, 1,
        1, -1, 0, 1
    ]);
    return createBufferWithData(device, { size: vertexArray.byteLength, usage: GPUBufferUsage.VERTEX }, vertexArray.buffer);
}

function createVertexInputDescriptor() {
    return {
        indexFormat: "uint32",
        vertexBuffers: [{
            stride: 4 * 4,
            attributeSet: [{
                format: "float4",
                shaderLocation: 0
            }]
        }]
    }
}

const canvas = document.querySelector("canvas");

async function test(device) {
    const swapChain = createBasicSwapChain(canvas, device);
    // FIXME: Replace with non-MSL shaders.
    const shaderModule = device.createShaderModule({ code: shaderCode });
    const vertexBuffer = createVertexBuffer(device);
    const vertexInputDescriptor = createVertexInputDescriptor();
    const depthStateDescriptor = createBasicDepthStateDescriptor();
    const pipeline = createBasicPipeline(shaderModule, device, null, null, vertexInputDescriptor, depthStateDescriptor);
    const commandEncoder = device.createCommandEncoder();

    const basicAttachment = {
        attachment: swapChain.getCurrentTexture().createDefaultView(),
        loadOp: "clear",
        storeOp: "store",
        clearColor: { r: 1.0, g: 0, b: 0, a: 1.0 }
    };

    const depthAttachment = {
        attachment: createBasicDepthTexture(canvas, device).createDefaultView(),
        depthLoadOp: "clear",
        depthStoreOp: "store",
        clearDepth: 1.0
    };

    const encoder = commandEncoder.beginRenderPass({
        colorAttachments: [basicAttachment],
        depthStencilAttachment: depthAttachment
    });

    encoder.setVertexBuffers(0, [vertexBuffer], [0]);
    encoder.setPipeline(pipeline);
    encoder.draw(4, 2, 0, 0);
    encoder.endPass();

    device.getQueue().submit([commandEncoder.finish()]);
}

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