blob: 004d0adf5dd730ed35d04a2c1abda76e54b0c19b [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<script src="../js/webgpu-functions.js"></script>
</head>
<body>
<canvas id="canvas" width="400" height="400"></canvas>
<script>
const shaderSource = `
struct Intermediate {
float4 position : SV_Position;
float2 textureCoordinate : attribute(0);
}
vertex Intermediate vertexShader(float4 position : attribute(0), float2 textureCoordinate : attribute(1)) {
Intermediate result;
result.position = position;
result.textureCoordinate = textureCoordinate;
return result;
}
fragment float4 fragmentShader(float2 textureCoordinate : attribute(0), Texture2D<float4> theTexture : register(t0), sampler theSampler : register(s1)) : SV_Target 0 {
return SampleBias(theTexture, theSampler, textureCoordinate, 1);
}
`;
const canvas = document.getElementById("canvas");
async function start(device) {
const shaderModule = device.createShaderModule({code: shaderSource});
const vertexStage = {module: shaderModule, entryPoint: "vertexShader"};
const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"};
const primitiveTopology = "triangle-strip";
const rasterizationState = {frontFace: "cw", cullMode: "none"};
const alphaBlend = {};
const colorBlend = {};
const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWrite.ALL
const depthStencilState = null;
const attribute0 = {shaderLocation: 0, format: "float4"};
const input0 = {stride: Float32Array.BYTES_PER_ELEMENT * 4, attributeSet: [attribute0]};
const attribute1 = {shaderLocation: 1, format: "float2"};
const input1 = {stride: Float32Array.BYTES_PER_ELEMENT * 2, attributeSet: [attribute1]};
const inputs = [input0, input1];
const vertexInput = {vertexBuffers: inputs};
const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "sampled-texture"}, {binding: 1, visibility: 7, type: "sampler"}]};
const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor);
const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]};
const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor);
const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout};
const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor);
const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 4 * 4 + Float32Array.BYTES_PER_ELEMENT * 2 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE};
const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor);
const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync();
const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer);
vertexBuffer0Float32Array[0] = -0.5;
vertexBuffer0Float32Array[1] = -0.5;
vertexBuffer0Float32Array[2] = 1.0;
vertexBuffer0Float32Array[3] = 1;
vertexBuffer0Float32Array[4] = -0.5;
vertexBuffer0Float32Array[5] = 0.5;
vertexBuffer0Float32Array[6] = 1.0;
vertexBuffer0Float32Array[7] = 1;
vertexBuffer0Float32Array[8] = 0.5;
vertexBuffer0Float32Array[9] = -0.5;
vertexBuffer0Float32Array[10] = 1.0;
vertexBuffer0Float32Array[11] = 1;
vertexBuffer0Float32Array[12] = 0.5;
vertexBuffer0Float32Array[13] = 0.5;
vertexBuffer0Float32Array[14] = 1.0;
vertexBuffer0Float32Array[15] = 1;
vertexBuffer0Float32Array[16] = 0;
vertexBuffer0Float32Array[17] = 0;
vertexBuffer0Float32Array[18] = 0;
vertexBuffer0Float32Array[19] = 100;
vertexBuffer0Float32Array[20] = 100;
vertexBuffer0Float32Array[21] = 0;
vertexBuffer0Float32Array[22] = 100;
vertexBuffer0Float32Array[23] = 100;
vertexBuffer0.unmap();
const textureDataBufferDescriptor = {size: Uint8Array.BYTES_PER_ELEMENT * 4 * 2 * 2 + Uint8Array.BYTES_PER_ELEMENT * 4 * 1 * 1, usage: GPUBufferUsage.COPY_SRC | GPUBufferUsage.MAP_WRITE};
const textureDataBuffer = device.createBuffer(textureDataBufferDescriptor);
const textureDataBufferArrayBuffer = await textureDataBuffer.mapWriteAsync();
const textureDataBufferUint8Array = new Uint8Array(textureDataBufferArrayBuffer);
textureDataBufferUint8Array[0] = 255;
textureDataBufferUint8Array[1] = 0;
textureDataBufferUint8Array[2] = 0;
textureDataBufferUint8Array[3] = 255;
textureDataBufferUint8Array[4] = 0;
textureDataBufferUint8Array[5] = 255;
textureDataBufferUint8Array[6] = 0;
textureDataBufferUint8Array[7] = 255;
textureDataBufferUint8Array[8] = 0;
textureDataBufferUint8Array[9] = 255
textureDataBufferUint8Array[10] = 0;
textureDataBufferUint8Array[11] = 255;
textureDataBufferUint8Array[12] = 255
textureDataBufferUint8Array[13] = 0;
textureDataBufferUint8Array[14] = 0;
textureDataBufferUint8Array[15] = 255;
textureDataBufferUint8Array[16] = 255;
textureDataBufferUint8Array[17] = 255;
textureDataBufferUint8Array[18] = 255;
textureDataBufferUint8Array[19] = 255;
textureDataBuffer.unmap();
const textureDescriptor = {size: {width: 2, height: 2, depth: 1}, mipLevelCount: 2, format: "rgba8unorm", usage: GPUTextureUsage.SAMPLED | GPUTextureUsage.COPY_DST};
const texture = device.createTexture(textureDescriptor);
const textureView = texture.createDefaultView();
const samplerDescriptor = {addressModeU: "repeat", addressModeV: "repeat", addressModeW: "repeat", magFilter: "linear", minFilter: "linear"};
const sampler = device.createSampler(samplerDescriptor);
const bindGroupBindings = [{binding: 0, resource: textureView}, {binding: 1, resource: sampler}];
const bindGroupDescriptor = {layout: bindGroupLayout, bindings: bindGroupBindings};
const bindGroup = device.createBindGroup(bindGroupDescriptor);
const context = canvas.getContext("gpu");
const swapChainDescriptor = {device, format: "bgra8unorm"};
const swapChain = context.configureSwapChain(swapChainDescriptor);
const outputTexture = swapChain.getCurrentTexture();
const outputTextureView = outputTexture.createDefaultView();
const commandEncoder = device.createCommandEncoder(); // {}
const bufferCopy1View = {buffer: textureDataBuffer, rowPitch: Uint8Array.BYTES_PER_ELEMENT * 4 * 2, imageHeight: Uint8Array.BYTES_PER_ELEMENT * 4 * 2 * 2};
const textureCopy1View = {texture: texture};
const copy1Size = {width: 2, height: 2, depth: 1};
commandEncoder.copyBufferToTexture(bufferCopy1View, textureCopy1View, copy1Size);
const bufferCopy2View = {buffer: textureDataBuffer, offset: Uint8Array.BYTES_PER_ELEMENT * 4 * 2 * 2, rowPitch: Uint8Array.BYTES_PER_ELEMENT * 4 * 1, imageHeight: Uint8Array.BYTES_PER_ELEMENT * 4 * 1 * 1};
const textureCopy2View = {texture: texture, mipLevel: 1};
const copy2Size = {width: 1, height: 1, depth: 1};
commandEncoder.copyBufferToTexture(bufferCopy2View, textureCopy2View, copy2Size);
const clearColor = {r: 0, g: 0, b: 1, a: 1};
const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor}];
const depthStencilAttachment = null;
const renderPassDescriptor = {colorAttachments, depthStencilAttachment};
const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
renderPassEncoder.setPipeline(renderPipeline);
renderPassEncoder.setBindGroup(0, bindGroup);
renderPassEncoder.setVertexBuffers(0, [vertexBuffer0, vertexBuffer0], [0, Float32Array.BYTES_PER_ELEMENT * 4 * 4]);
renderPassEncoder.draw(4, 1, 0, 0);
renderPassEncoder.endPass();
const commandBuffer = commandEncoder.finish();
device.getQueue().submit([commandBuffer]);
if (window.testRunner)
testRunner.notifyDone();
}
if (window.testRunner)
testRunner.waitUntilDone();
getBasicDevice().then(function(device) {
start(device).then(function() {
if (window.testRunner)
testRunner.notifyDone();
}, function() {
if (window.testRunner)
testRunner.notifyDone();
});
}, function() {
drawWhiteSquareOnBlueBackgroundInSoftware(canvas);
if (window.testRunner)
testRunner.notifyDone();
});
</script>
</body>
</html>