<!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 createInputStateDescriptor() {
    return {
        indexFormat: "uint32",
        attributes: [{
            shaderLocation: positionAttributeNum,
            inputSlot: positionBufferIndex,
            format: "float4"
        }, {
            shaderLocation: texCoordsAttributeNum,
            inputSlot: texCoordsBufferIndex,
            format: "float2"
        }],
        inputs: [{
            inputSlot: positionBufferIndex,
            stride: 4 * 4
        }, {
            inputSlot: texCoordsBufferIndex,
            stride: 4 * 2
        }]
    }
}

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 = device.createBuffer({ size: positionArray.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.TRANSFER_DST });
    positionBuffer.setSubData(0, positionArray.buffer);

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

    const inputStateDescriptor = createInputStateDescriptor();

    // 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 | GPUBufferUsage.TRANSFER_DST
    };
    const textureBuffer = device.createBuffer(textureBufferDescriptor);
    textureBuffer.setSubData(0, 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, inputStateDescriptor);
    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();

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

test();
</script>