<!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 = `
struct VertexOut
{
    float4 position : SV_Position;
    float2 texCoords : attribute(0);
};

vertex VertexOut vertex_main(float4 position : attribute(${positionAttributeNum}), float2 texCoords : attribute(${texCoordsAttributeNum})) {
    VertexOut vOut;
    vOut.position = position;
    vOut.texCoords = texCoords;
    return vOut;
}

struct TextureSampler
{
    Texture2D<float4> t : register(t${textureBindingNum}, space${bindGroupIndex});
    sampler s : register(s${samplerBindingNum}, space${bindGroupIndex});
};

fragment float4 fragment_main(float2 texCoords : attribute(0), TextureSampler textureSampler) : SV_Target 0
{
    return Sample(textureSampler.t, textureSampler.s, 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 };
}

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 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.COPY_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.COPY_DST | GPUTextureUsage.SAMPLED
    };
    const texture = device.createTexture(textureDescriptor);

    // Bind texture and a sampler to pipeline
    const textureLayoutBinding = { 
        binding: textureBindingNum, 
        visibility: GPUShaderStage.FRAGMENT, 
        type: "sampled-texture" 
    };
    const samplerLayoutBinding = {
        binding: samplerBindingNum,
        visibility: GPUShaderStage.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();
}

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>
