<!DOCTYPE html>
<meta charset=utf-8>
<title>Create a basic GPUBindGroup.</title>
<body>
<script src="js/webgpu-functions.js"></script>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script>
let tests = {};

const basicBufferShader = `
[numthreads(1, 1, 1)]
compute void compute_main(device int[] buffer : register(u0))
{
    ++buffer[0];
}
`;

let basicPipeline;

tests["Create and use a basic GPUBindGroup."] = async device => {
    const bufferLayoutBinding = {
        binding: 0,
        visibility: GPUShaderStage.COMPUTE,
        type: "storage-buffer"
    };

    const bindGroupLayout = device.createBindGroupLayout({ bindings: [bufferLayoutBinding] });

    const basicBuffer = device.createBuffer({ size: 4, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.MAP_READ });
    const bufferBinding = { buffer: basicBuffer, size: 4 };
    const bindGroupBinding = { binding: 0, resource: bufferBinding };

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

    const pipelineLayout = device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] });

    const basicShaderModule = device.createShaderModule({ code: basicBufferShader });
    basicPipeline = device.createComputePipeline({
        layout: pipelineLayout,
        computeStage: {
            module: basicShaderModule,
            entryPoint: "compute_main"
        }
    });

    const commandEncoder = device.createCommandEncoder();
    const passEncoder = commandEncoder.beginComputePass();
    passEncoder.setPipeline(basicPipeline);
    passEncoder.setBindGroup(0, bindGroup);
    passEncoder.dispatch(1, 1, 1);
    passEncoder.endPass();
    device.getQueue().submit([commandEncoder.finish()]);

    const results = new Int32Array(await basicBuffer.mapReadAsync());
    basicBuffer.unmap();
    assert_equals(results[0], 1, "Storage buffer binding written to successfully.");
};

tests["Create and use many GPUBindGroups in a single compute pass."] = async device => {
    const bufferLayoutBinding = {
        binding: 0,
        visibility: GPUShaderStage.COMPUTE,
        type: "storage-buffer"
    };

    const bindGroupLayout = device.createBindGroupLayout({ bindings: [bufferLayoutBinding] });

    const basicBuffer = device.createBuffer({ size: 4, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.MAP_READ });
    const bufferBinding = { buffer: basicBuffer, size: 4 };
    const bindGroupBinding = { binding: 0, resource: bufferBinding };

    const numGroups = 1000;
    let bindGroups = new Array(numGroups);
    for (let i = 0; i < numGroups; ++i)
        bindGroups[i] = device.createBindGroup({ layout: bindGroupLayout, bindings: [bindGroupBinding] });

    const commandEncoder = device.createCommandEncoder();
    const passEncoder = commandEncoder.beginComputePass();

    let j = 0;
    for (; j < numGroups; ++j) {
        passEncoder.setPipeline(basicPipeline);
        passEncoder.setBindGroup(0, bindGroups[j]);
        passEncoder.dispatch(1, 1, 1);
    }

    passEncoder.endPass();
    device.getQueue().submit([commandEncoder.finish()]);

    const results = new Int32Array(await basicBuffer.mapReadAsync());
    basicBuffer.unmap();
    assert_equals(results[0], j, "Storage buffer accessed successfully through multiple bind groups.");
};

const uniformBufferShader = `
[numthreads(1, 1, 1)]
compute void compute_main(constant int[] uniforms : register(b0), device int[] buffer : register(u1))
{
    buffer[0] += uniforms[0];
}
`;

tests["Create and access a uniform-buffer in a GPUBindGroup."] = async device => {
    const [uniformBuffer, writeArrayBuffer] = device.createBufferMapped({ size: 4, usage: GPUBufferUsage.UNIFORM });
    new Int32Array(writeArrayBuffer).set([42]);
    uniformBuffer.unmap();

    const storageBuffer = device.createBuffer({ size: 4, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.MAP_READ });

    const bindGroupLayout = device.createBindGroupLayout({
        bindings: [{
            binding: 0,
            visibility: GPUShaderStage.COMPUTE,
            type: "uniform-buffer"
        }, {
            binding: 1,
            visibility: GPUShaderStage.COMPUTE,
            type: "storage-buffer"
        }]
    });

    const bindGroup = device.createBindGroup({
        layout: bindGroupLayout,
        bindings: [{
            binding: 0,
            resource: {
                buffer: uniformBuffer,
                size: 4
            }
        }, {
            binding: 1,
            resource: {
                buffer: storageBuffer,
                size: 4
            }
        }]
    });

    const pipelineLayout = device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] });

    const shaderModule = device.createShaderModule({ code: uniformBufferShader });

    const pipeline = device.createComputePipeline({
        layout: pipelineLayout,
        computeStage: {
            module: shaderModule,
            entryPoint: "compute_main"
        }
    });

    const commandEncoder = device.createCommandEncoder();
    const passEncoder = commandEncoder.beginComputePass();
    passEncoder.setPipeline(pipeline);
    passEncoder.setBindGroup(0, bindGroup);
    passEncoder.dispatch(1, 1, 1);
    passEncoder.endPass();
    device.getQueue().submit([commandEncoder.finish()]);

    const results = new Int32Array(await storageBuffer.mapReadAsync());
    storageBuffer.unmap();
    assert_equals(results[0], 42, "Storage buffer binding written to successfully.");
};

const sampledTextureShader = `
[numthreads(1, 1, 1)]
compute void compute_main(Texture2D<uint> inputTexture : register(t0), sampler inputSampler : register(s1), device uint[] output : register(u2))
{
    output[0] = Sample(inputTexture, inputSampler, float2(0, 0));
}
`;

tests["Create and access a sampled texture in a GPUBindGroup."] = async device => {
    const [textureDataBuffer, textureArrayBuffer] = device.createBufferMapped({ size: 4, usage: GPUBufferUsage.COPY_SRC });
    new Uint32Array(textureArrayBuffer).set([42]);
    textureDataBuffer.unmap();

    const textureSize = { width: 1, height: 1, depth: 1 };
    const texture = device.createTexture({
        size: textureSize,
        format: "rgba8uint",
        usage: GPUTextureUsage.SAMPLED | GPUTextureUsage.COPY_DST
    });

    const outputBuffer = device.createBuffer({ size: 4, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.MAP_READ });

    const bindGroupLayout = device.createBindGroupLayout({
        bindings: [{
            binding: 0,
            visibility: GPUShaderStage.COMPUTE,
            type: "sampled-texture"
        }, {
            binding: 1,
            visibility: GPUShaderStage.COMPUTE,
            type: "sampler"
        }, {
            binding: 2,
            visibility: GPUShaderStage.COMPUTE,
            type: "storage-buffer"
        }]
    });
    const bindGroup = device.createBindGroup({
        layout: bindGroupLayout,
        bindings: [{
            binding: 0,
            resource: texture.createDefaultView()
        }, {
            binding: 1,
            resource: device.createSampler({})
        }, {
            binding: 2,
            resource: {
                buffer: outputBuffer,
                size: 4
            }
        }]
    });

    const shaderModule = device.createShaderModule({ code: sampledTextureShader });
    const pipelineLayout = device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] });

    const pipeline = device.createComputePipeline({
        layout: pipelineLayout,
        computeStage: {
            module: shaderModule,
            entryPoint: "compute_main"
        }
    });

    const commandEncoder = device.createCommandEncoder();
    commandEncoder.copyBufferToTexture({
        buffer: textureDataBuffer,
        rowPitch: 4,
        imageHeight: 0
    }, { texture: texture }, textureSize);

    const passEncoder = commandEncoder.beginComputePass();
    passEncoder.setPipeline(pipeline);
    passEncoder.setBindGroup(0, bindGroup);
    passEncoder.dispatch(1, 1, 1);
    passEncoder.endPass();

    device.getQueue().submit([commandEncoder.finish()]);

    const results = new Uint32Array(await outputBuffer.mapReadAsync());
    outputBuffer.unmap();
    assert_equals(results[0], 42, "Correct value sampled from a bound 2D texture.");
};

const comboShader = `
[numthreads(1, 1, 1)]
compute void compute_main(
    Texture2D<uint> inputTexture : register(t0, space0), 
    sampler inputSampler : register(s0, space1), 
    constant uint[] input : register(b0, space2), 
    device uint[] output : register(u0, space3))
{
    output[0] = input[0] + Sample(inputTexture, inputSampler, float2(0, 0));
}
`;

tests["Create and use multiple GPUBindGroups in a single dispatch."] = async device => {
    const [textureDataBuffer, textureArrayBuffer] = device.createBufferMapped({ size: 4, usage: GPUBufferUsage.COPY_SRC });
    new Uint32Array(textureArrayBuffer).set([17]);
    textureDataBuffer.unmap();

    const textureSize = { width: 1, height: 1, depth: 1 };
    const texture = device.createTexture({
        size: textureSize,
        format: "rgba8uint",
        usage: GPUTextureUsage.SAMPLED | GPUTextureUsage.COPY_DST
    });

    const [inputBuffer, inputArrayBuffer] = device.createBufferMapped({ size: 4, usage: GPUBufferUsage.UNIFORM });
    new Uint32Array(inputArrayBuffer).set([25]);
    inputBuffer.unmap();

    const outputBuffer = device.createBuffer({ size: 4, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.MAP_READ });

    const bgl0 = device.createBindGroupLayout({
        bindings: [{
            binding: 0,
            visibility: GPUShaderStage.COMPUTE,
            type: "sampled-texture"
        }]
    });
    const bgl1 = device.createBindGroupLayout({
        bindings: [{
            binding: 0,
            visibility: GPUShaderStage.COMPUTE,
            type: "sampler"
        }]
    });
    const bgl2 = device.createBindGroupLayout({
        bindings: [{
            binding: 0,
            visibility: GPUShaderStage.COMPUTE,
            type: "uniform-buffer"
        }]
    });
    const bgl3 = device.createBindGroupLayout({
        bindings: [{
            binding: 0,
            visibility: GPUShaderStage.COMPUTE,
            type: "storage-buffer"
        }]
    })

    const bg0 = device.createBindGroup({
        layout: bgl0,
        bindings: [{
            binding: 0,
            resource: texture.createDefaultView()
        }]
    });
    const bg1 = device.createBindGroup({
        layout: bgl1,
        bindings: [{
            binding: 0,
            resource: device.createSampler({})
        }]
    });
    const bg2 = device.createBindGroup({
        layout: bgl2,
        bindings: [{
            binding: 0,
            resource: {
                buffer: inputBuffer,
                size: 4
            }
        }]
    });
    const bg3 = device.createBindGroup({
        layout: bgl3,
        bindings: [{
            binding: 0,
            resource: {
                buffer: outputBuffer,
                size: 4
            }
        }]
    });

    const shaderModule = device.createShaderModule({ code: comboShader });
    const pipelineLayout = device.createPipelineLayout({ bindGroupLayouts: [bgl0, bgl1, bgl2, bgl3] });

    const pipeline = device.createComputePipeline({
        layout: pipelineLayout,
        computeStage: {
            module: shaderModule,
            entryPoint: "compute_main"
        }
    });

    const commandEncoder = device.createCommandEncoder();
    commandEncoder.copyBufferToTexture({
        buffer: textureDataBuffer,
        rowPitch: 4,
        imageHeight: 0
    }, { texture: texture }, textureSize);

    const passEncoder = commandEncoder.beginComputePass();
    passEncoder.setPipeline(pipeline);
    passEncoder.setBindGroup(0, bg0);
    passEncoder.setBindGroup(1, bg1);
    passEncoder.setBindGroup(2, bg2);
    passEncoder.setBindGroup(3, bg3);
    passEncoder.dispatch(1, 1, 1);
    passEncoder.endPass();

    device.getQueue().submit([commandEncoder.finish()]);

    const results = new Uint32Array(await outputBuffer.mapReadAsync());
    outputBuffer.unmap();
    assert_equals(results[0], 42, "Correct value sampled from a bound 2D texture.");
};

tests["Bind a single GPUBuffer with different offsets in different GPUBindGroups"] = async device => {
    const numInputs = 4;
    const [uniformBuffer, writeArrayBuffer] = device.createBufferMapped({ size: 4 * numInputs, usage: GPUBufferUsage.UNIFORM });
    new Int32Array(writeArrayBuffer).set([1, 2, 3, 36]);
    uniformBuffer.unmap();

    const storageBuffer = device.createBuffer({ size: 4, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.MAP_READ });

    const bindGroupLayout = device.createBindGroupLayout({
        bindings: [{
            binding: 0,
            visibility: GPUShaderStage.COMPUTE,
            type: "uniform-buffer"
        }, {
            binding: 1,
            visibility: GPUShaderStage.COMPUTE,
            type: "storage-buffer"
        }]
    });

    let bindGroups = new Array(numInputs);
    for (let i = 0; i < numInputs; ++i) {
        bindGroups[i] = device.createBindGroup({
            layout: bindGroupLayout,
            bindings: [{
                binding: 0,
                resource: {
                    buffer: uniformBuffer,
                    offset: i * numInputs,
                    size: 4
                }
            }, {
                binding: 1,
                resource: {
                    buffer: storageBuffer,
                    size: 4
                }
            }]
        });
    }

    const pipelineLayout = device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] });

    const shaderModule = device.createShaderModule({ code: uniformBufferShader });

    const pipeline = device.createComputePipeline({
        layout: pipelineLayout,
        computeStage: {
            module: shaderModule,
            entryPoint: "compute_main"
        }
    });

    const commandEncoder = device.createCommandEncoder();
    const passEncoder = commandEncoder.beginComputePass();
    passEncoder.setPipeline(pipeline);
    for (let i = 0; i < numInputs; ++i) {
        passEncoder.setBindGroup(0, bindGroups[i]);
        passEncoder.dispatch(1, 1, 1);
    }
    passEncoder.endPass();
    device.getQueue().submit([commandEncoder.finish()]);

    const results = new Int32Array(await storageBuffer.mapReadAsync());
    storageBuffer.unmap();
    assert_equals(results[0], 42, "Storage buffer binding written to successfully.");
};

runTestsWithDevice(tests);
</script>
</body>
