<!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 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 positionBufferIndex = 0;
const texCoordsBufferIndex = 1;
const positionAttributeNum = 0;
const texCoordsAttributeNum = 1;
const bindGroupIndex = 0;
const textureBindingNum = 0;
const samplerBindingNum = 1;

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

struct VertexIn
{
    float4 position [[attribute(${positionAttributeNum})]];
    float2 texCoords [[attribute(${texCoordsAttributeNum})]];
};

struct VertexOut
{
    float4 position [[position]];
    float2 texCoords;
};

vertex VertexOut vertex_main(VertexIn vertexIn [[stage_in]])
{
    VertexOut vOut;
    vOut.position = vertexIn.position;
    vOut.texCoords = vertexIn.texCoords;
    return vOut;
}

struct TextureSampler
{
    texture2d<float> t [[id(${textureBindingNum})]];
    sampler s [[id(${samplerBindingNum})]];
};

fragment float4 fragment_main(VertexOut v [[stage_in]], const device TextureSampler& args [[buffer(${bindGroupIndex})]])
{
    return args.t.sample(args.s, v.texCoords);
}
`

function createVertexInputDescriptor() {
    var bufferDescriptors = [];
    bufferDescriptors[positionBufferIndex] = {
        stride: 4 * 4,
        attributeSet: [{
            format: "float4",
            shaderLocation: positionAttributeNum
        }]
    };
    bufferDescriptors[texCoordsBufferIndex] = {
        stride: 4 * 2,
        attributeSet: [{
            format: "float2",
            shaderLocation: texCoordsAttributeNum
        }]
    };

    return { vertexBuffers: bufferDescriptors };
}

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 positionArray = new Float32Array([
        // float4 xyzw
        -1, 1, 0, 1,
        -1, -1, 0, 1,
        1, 1, 0, 1, 
        1, -1, 0, 1
    ]);
    const positionBuffer = createBufferWithData(device, { size: positionArray.byteLength, usage: GPUBufferUsage.VERTEX }, positionArray.buffer);

    const texCoordsArray = new Float32Array([
        // float2 texCoords
        0, 0,
        0, 1,
        1, 0,
        1, 1
    ]);
    const textureCoordBuffer = createBufferWithData(device, { size: texCoordsArray.byteLength, usage: GPUBufferUsage.VERTEX }, texCoordsArray.buffer);

    const vertexInputDescriptor = createVertexInputDescriptor();

    // Load texture image
    const image = new Image();
    const imageLoadPromise = new Promise(resolve => { 
        image.onload = () => resolve(); 
        image.src = "resources/blue-checkered.png";
    });
    await Promise.resolve(imageLoadPromise);

    // Convert image to data and fill GPUBuffer
    const canvas2d = document.createElement("canvas");
    canvas2d.width = image.width;
    canvas2d.height = image.height;
    const context2d = canvas2d.getContext("2d");
    context2d.drawImage(image, 0, 0);
    const imageData = context2d.getImageData(0, 0, image.width, image.height);

    const textureBufferDescriptor = {
        size: imageData.data.length,
        usage: GPUBufferUsage.TRANSFER_SRC
    };
    const textureBuffer = createBufferWithData(device, textureBufferDescriptor, imageData.data.buffer);

    // Create GPUTexture
    const textureSize = {
        width: image.width,
        height: image.height,
        depth: 1
    };

    const textureDescriptor = {
        size: { width: image.width, height: image.height, depth: 1 },
        format: "rgba8unorm",
        usage: GPUTextureUsage.TRANSFER_DST | GPUTextureUsage.SAMPLED
    };
    const texture = device.createTexture(textureDescriptor);

    // Bind texture and a sampler to pipeline
    const textureLayoutBinding = { 
        binding: textureBindingNum, 
        visibility: GPUShaderStageBit.FRAGMENT, 
        type: "sampled-texture" 
    };
    const samplerLayoutBinding = {
        binding: samplerBindingNum,
        visibility: GPUShaderStageBit.FRAGMENT,
        type: "sampler"
    };

    const bindGroupLayoutDescriptor = {
        bindings: [textureLayoutBinding, samplerLayoutBinding]
    };
    bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor);
    const pipelineLayout = device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] });

    const textureBinding = { 
        binding: textureBindingNum, 
        resource: texture.createDefaultView() 
    };
    const samplerBinding = {
        binding: samplerBindingNum,
        resource: device.createSampler({ minFilter: "nearest", magFilter: "nearest" })
    };

    const bindGroupDescriptor = {
        layout: bindGroupLayout,
        bindings: [textureBinding, samplerBinding]
    };
    const bindGroup = device.createBindGroup(bindGroupDescriptor);

    // Pipeline and render
    const pipeline = createBasicPipeline(shaderModule, device, null, pipelineLayout, vertexInputDescriptor);
    const commandEncoder = device.createCommandEncoder();

    const bufferCopyView = {
        buffer: textureBuffer,
        rowPitch: image.width * 4,
        imageHeight: 0
    };
    const textureCopyView = { texture: texture };
    commandEncoder.copyBufferToTexture(bufferCopyView, textureCopyView, textureSize);
    const passEncoder = beginBasicRenderPass(swapChain, commandEncoder);
    passEncoder.setPipeline(pipeline);
    passEncoder.setBindGroup(bindGroupIndex, bindGroup);
    passEncoder.setVertexBuffers(positionBufferIndex, [positionBuffer, textureCoordBuffer], [0, 0]);
    passEncoder.draw(4, 1, 0, 0);
    passEncoder.endPass();

    const queue = device.getQueue();
    queue.submit([commandEncoder.finish()]);
    positionBuffer.destroy();
    textureCoordBuffer.destroy();
    texture.destroy();
}

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