<!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="viewport-scissor-rect-triangle-strip-expected.html">
<p>Pass if square canvas below is a 4 by 4 blue/green checkerboard.</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 Vertex
{
    float4 position [[position]];
};

vertex Vertex vertex_main(uint vid [[vertex_id]])
{
    Vertex v;
    switch (vid) {
    case 0:
        v.position = float4(-1, 1, 0, 1);
        break;
    case 1:
        v.position = float4(-1, -1, 0, 1);
        break;
    case 2:
        v.position = float4(1, 1, 0, 1);
        break;
    default:
        v.position = float4(1, -1, 0, 1);
    }
    return v;
}

fragment float4 fragment_main(Vertex vertexIn [[stage_in]])
{
    return float4(0.0, 1.0, 0.0, 1.0);
}
`;

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

async function test(device) {
    const canvas = document.querySelector("canvas");
    const swapChain = createBasicSwapChain(canvas, device);
    // FIXME: Replace with non-MSL shaders.
    const shaderModule = device.createShaderModule({ code: shaderCode });
    const pipeline = createBasicPipeline(shaderModule, device);
    const commandEncoder = device.createCommandEncoder();
    const blueAttachment = {
        attachment: swapChain.getCurrentTexture().createDefaultView(),
        loadOp: "clear",
        storeOp: "store",
        clearColor: { r: 0, g: 0, b: 1, a: 1 }
    };
    const passEncoder = commandEncoder.beginRenderPass({ colorAttachments: [blueAttachment] });
    passEncoder.setPipeline(pipeline);

    function drawViewport(x, y) {
        passEncoder.setViewport(x, y, 100, 100, 0, 1);
        passEncoder.draw(4, 1, 0, 0);
    }

    function drawScissorRect(x, y) {
        passEncoder.setScissorRect(x, y, 100, 100);
        passEncoder.draw(4, 1, 0, 0);
    }

    passEncoder.setScissorRect(0, 0, 200, 400);
    drawViewport(100, 0);
    drawViewport(0, 100);
    drawViewport(100, 200);
    drawViewport(0, 300);

    // Draw outside of scissor rect should not appear.
    drawViewport(200, 100);

    passEncoder.setViewport(200, 0, 200, 400, 0, 1);
    drawScissorRect(300, 0);
    drawScissorRect(200, 100);
    drawScissorRect(300, 200);
    drawScissorRect(200, 300);

    // Draw outside of viewport should not appear.
    drawScissorRect(0, 0);

    passEncoder.endPass();
    const queue = device.getQueue();

    queue.submit([commandEncoder.finish()]);
}

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