| <!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 completely green.</p> |
| <canvas width="400" height="400"></canvas> |
| <script src="js/webgpu-functions.js"></script> |
| <script> |
| if (window.testRunner) |
| testRunner.waitUntilDone(); |
| |
| const shaderCode = ` |
| struct VertexOut |
| { |
| float4 position : SV_Position; |
| float4 color : attribute(0); |
| }; |
| |
| vertex VertexOut vertex_main(float4 position : attribute(0), float green : attribute(1)) |
| { |
| VertexOut vOut; |
| vOut.position = position; |
| vOut.color = float4(0, green, 0, 1); |
| return vOut; |
| } |
| |
| fragment float4 fragment_main(float4 color : attribute(0)) : SV_Target 0 |
| { |
| return color; |
| } |
| ` |
| |
| function createVertexBuffer(device) { |
| const vertexArray = new Float32Array([ |
| // float4 xyzw, float g |
| -1, 1, 0, 1, 1, |
| -1, -1, 0, 1, 1, |
| 1, 1, 0, 1, 1, |
| 1, -1, 0, 1, 1 |
| ]); |
| |
| return createBufferWithData( |
| device, |
| { |
| size: vertexArray.byteLength, |
| usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE |
| }, |
| vertexArray.buffer |
| ); |
| } |
| |
| function createVertexInputDescriptor() { |
| return { |
| vertexBuffers: [{ |
| stride: 4 * 5, |
| attributeSet: [{ |
| format: "float4", |
| shaderLocation: 0 |
| }, { |
| offset: 4 * 4, |
| format: "float", |
| shaderLocation: 1 |
| }] |
| }] |
| } |
| } |
| |
| 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 vertexBuffer = createVertexBuffer(device); |
| const vertexInputDescriptor = createVertexInputDescriptor(); |
| const pipeline = createBasicPipeline(shaderModule, device, null, null, vertexInputDescriptor); |
| const commandEncoder = device.createCommandEncoder(); |
| const passEncoder = beginBasicRenderPass(swapChain, commandEncoder); |
| encodeBasicCommands(passEncoder, pipeline, vertexBuffer); |
| const queue = device.getQueue(); |
| queue.submit([commandEncoder.finish()]); |
| vertexBuffer.destroy(); |
| } |
| |
| getBasicDevice().then(function(device) { |
| test(device).then(function() { |
| if (window.testRunner) |
| testRunner.notifyDone(); |
| }, function() { |
| if (window.testRunner) |
| testRunner.notifyDone(); |
| }); |
| }, function() { |
| drawGreenSquareInSoftware(canvas); |
| if (window.testRunner) |
| testRunner.notifyDone(); |
| }); |
| </script> |