async function getBasicDevice() {
    const adapter = await navigator.gpu.requestAdapter({ powerPreference: "low-power" });
    const device = await adapter.requestDevice();
    return device;
}

function drawGreenMipChainOnRedBackgroundInSoftware(canvas) {
    const context = canvas.getContext("2d");
    context.fillStyle = "rgb(255, 0, 0)";
    context.fillRect(0, 0, canvas.width, canvas.height);

    let maxResolution = Math.max(canvas.width, canvas.height);
    let mipLevelCount = Math.ceil(Math.log2(maxResolution));
    if (mipLevelCount < 1) mipLevelCount = 1;

    let width  = canvas.width;
    let height = canvas.height;
    for (var i = 1; i < mipLevelCount; ++i) {
        width  = Math.max(Math.floor(width  / 2), 1);
        height = Math.max(Math.floor(height / 2), 1);
        context.fillStyle = "rgb(0, 255, 0)";
        context.fillRect(0, height, width, height);
    }

}

function drawWhiteSquareOnBlueBackgroundInSoftware(canvas) {
    const context = canvas.getContext("2d");
    context.fillStyle = "blue";
    context.fillRect(0, 0, 400, 400);
    context.fillStyle = "white";
    context.fillRect(100, 100, 200, 200);
}

function drawBlackSquareOnBlueBackgroundInSoftware(canvas) {
    const context = canvas.getContext("2d");
    context.fillStyle = "blue";
    context.fillRect(0, 0, 400, 400);
    context.fillStyle = "black";
    context.fillRect(100, 100, 200, 200);
}

function drawGreenSquareInSoftware(canvas) {
    const context = canvas.getContext('2d');
    context.fillStyle = 'rgb(0, 255, 0)';
    context.fillRect(0, 0, canvas.width, canvas.height);
}

function drawGreenAndBlueCheckerboardInSoftware(canvas) {
    const context = canvas.getContext('2d');

    context.fillStyle = 'rgb(0, 255, 0)';
    context.fillRect(0, 0, canvas.width, canvas.height);

    const numColumns = 4;
    const numRows = 4;
    context.beginPath();
    context.fillStyle = 'rgb(0, 0, 255)';
    for (let x = 0; x < numColumns; ++x) {
        for (let y = 0; y < numRows; ++y) {
            if ((x + y) % 2 == 0)
                context.rect(
                    x * canvas.width / numColumns,
                    y * canvas.height / numRows,
                    canvas.width / numColumns,
                    canvas.height / numRows
                    );
        }
    }
    context.fill();
}

function createBasicSwapChain(canvas, device) {
    const context = canvas.getContext("gpu");
    return context.configureSwapChain({ device: device, format: "bgra8unorm" });
}

function createBasicDepthStateDescriptor() {
    return {
        depthWriteEnabled: true,
        depthCompare: "less"
    };
}

function createBasicDepthTexture(canvas, device) {
    const depthSize = {
        width: canvas.width,
        height: canvas.height,
        depth: 1
    };

    return device.createTexture({
        size: depthSize,
        format: "depth32float-stencil8",
        usage: GPUTextureUsage.OUTPUT_ATTACHMENT
    });
}

function createBasicPipeline(shaderModule, device, colorStates, pipelineLayout, vertexInputDescriptor, depthStateDescriptor, primitiveTopology = "triangle-strip") {
    const vertexStageDescriptor = {
        module: shaderModule,
        entryPoint: "vertex_main" 
    };

    const fragmentStageDescriptor = {
        module: shaderModule,
        entryPoint: "fragment_main"
    };

    if (!colorStates) {
        colorStates = [{ 
            format: "bgra8unorm",
            alphaBlend: {},
            colorBlend: {}
        }];
    }

    if (!vertexInputDescriptor)
        vertexInputDescriptor = { vertexBuffers: [] };

    const pipelineDescriptor = {
        vertexStage: vertexStageDescriptor,
        fragmentStage: fragmentStageDescriptor,
        primitiveTopology: primitiveTopology,
        colorStates: colorStates,
        vertexInput: vertexInputDescriptor
    };

    if (pipelineLayout)
        pipelineDescriptor.layout = pipelineLayout;

    if (depthStateDescriptor)
        pipelineDescriptor.depthStencilState = depthStateDescriptor;

    return device.createRenderPipeline(pipelineDescriptor);
}

function beginBasicRenderPass(swapChain, commandEncoder) {
    const basicAttachment = {
        attachment: swapChain.getCurrentTexture().createDefaultView(),
        loadOp: "clear",
        storeOp: "store",
        clearColor: { r: 1.0, g: 0, b: 0, a: 1.0 }
    };

    // FIXME: Flesh out the rest of GPURenderPassDescriptor. 
    return commandEncoder.beginRenderPass({ colorAttachments : [basicAttachment] });
}

function encodeBasicCommands(renderPassEncoder, renderPipeline, vertexBuffer) {
    if (vertexBuffer)
        renderPassEncoder.setVertexBuffers(0, [vertexBuffer], [0]);
    renderPassEncoder.setPipeline(renderPipeline);
    renderPassEncoder.draw(4, 1, 0, 0);
    renderPassEncoder.endPass();
}

function createBufferWithData(device, descriptor, data, offset = 0) {
    const mappedBuffer = device.createBufferMapped(descriptor);
    const dataArray = new Uint8Array(mappedBuffer[1]);
    dataArray.set(new Uint8Array(data), offset);
    mappedBuffer[0].unmap();
    return mappedBuffer[0];
}

async function mapWriteDataToBuffer(buffer, data, offset = 0) {
    const arrayBuffer = await buffer.mapWriteAsync();
    const writeArray = new Uint8Array(arrayBuffer);
    writeArray.set(new Uint8Array(data), offset);
    buffer.unmap();
}

/*** Functions below this line require WPT testharness.js and testharnessreport.js. ***/

function runTestsWithDevice(tests) {
    window.addEventListener("load", async () => {
        try {
            var device = await getBasicDevice();
        } catch (e) { /* WebGPU is not supported. */ }
    
        for (let name in tests) {
            if (!name.startsWith("_"))
                devicePromiseTest(device, tests[name], name);
        }
    });
}

function devicePromiseTest(device, func, name) {
    promise_test(async () => {
        if (device === undefined)
            return Promise.resolve();
        return func(device);
    }, name);
};

// Asserting errors.

const popValidationError = device => device.popErrorScope().then(error => assertValidationError(error));
const popMemoryError = device => device.popErrorScope().then(error => assertMemoryError(error));
const popNullError = device => device.popErrorScope().then(error => assertNull(error));
const assertNull = error => {
    let assertionMsg = "No error expected!";
    if (error && error.message)
        assertionMsg += " Got: " + error.message;
    assert_true(error === null, assertionMsg);
};
const assertValidationError = error => {
    let assertionMsg = "Expected validation error: ";
    if (error && error.message)
        assertionMsg += error.message;
    assert_true(error instanceof GPUValidationError, assertionMsg);
};
const assertMemoryError = error => assert_true(error instanceof GPUOutOfMemoryError, "Expected out-of-memory error!");
