<!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 = `
#include <metal_stdlib>
    
using namespace metal;

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

struct VertexOut
{
    float4 position [[position]];
    float4 color;
};

vertex VertexOut vertex_main(VertexIn vertexIn [[stage_in]], uint iid [[instance_id]])
{
    VertexOut vOut;
    vOut.position = vertexIn.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(VertexOut v [[stage_in]])
{
    return v.color;
}
`

function createVertexBuffer(device) {
    const bufferSize = 4 * 4 * 4;
    const buffer = device.createBuffer({ size: bufferSize, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST });
    const arrayBuffer = new Float32Array([
        // float4 xyzw
        -1, 1, 0, 1,
        -1, -1, 0, 1,
        1, 1, 0, 1,
        1, -1, 0, 1
    ]).buffer;
    
    buffer.setSubData(0, arrayBuffer);
    return buffer;
}

function createInputStateDescriptor() {
    return {
        indexFormat: "uint32",
        attributes: [{
            shaderLocation: 0,
            inputSlot: 0,
            format: "float4"
        }],
        inputs: [{
            inputSlot: 0,
            stride: 4 * 4
        }]
    }
}

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 });
    const vertexBuffer = createVertexBuffer(device);
    const inputStateDescriptor = createInputStateDescriptor();
    const depthStateDescriptor = createBasicDepthStateDescriptor();
    const pipeline = createBasicPipeline(shaderModule, device, null, null, inputStateDescriptor, 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()]);

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

test();
</script>