1*c8dee2aaSAndroid Build Coastguard Worker<!DOCTYPE html> 2*c8dee2aaSAndroid Build Coastguard Worker<title>Web GPU Demo</title> 3*c8dee2aaSAndroid Build Coastguard Worker<meta charset="utf-8" /> 4*c8dee2aaSAndroid Build Coastguard Worker<meta http-equiv="X-UA-Compatible" content="IE=edge"> 5*c8dee2aaSAndroid Build Coastguard Worker<meta name="viewport" content="width=device-width, initial-scale=1.0"> 6*c8dee2aaSAndroid Build Coastguard Worker<!-- For *.skia.org https://developer.chrome.com/origintrials/#/registration/2983494015644598273 7*c8dee2aaSAndroid Build Coastguard Worker Expires Nov 19, 2021 8*c8dee2aaSAndroid Build Coastguard Worker --> 9*c8dee2aaSAndroid Build Coastguard Worker<meta http-equiv="origin-trial" content="AnRs8mYss+Awd1DPUg2VfjXJbw2087/Dysaa3L7JmrbzTkwoEr87cX3y0zUfTGOFSLKJLRqNEmFAwfy+uumVXQsAAABbeyJvcmlnaW4iOiJodHRwczovL3NraWEub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJHUFUiLCJleHBpcnkiOjE2NDMxNTUxOTksImlzU3ViZG9tYWluIjp0cnVlfQ=="> 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker<!-- For localhost:8123 https://developer.chrome.com/origintrials/#/registration/6568359319031513089 12*c8dee2aaSAndroid Build Coastguard Worker Expires Nov 19, 2021 13*c8dee2aaSAndroid Build Coastguard Worker --> 14*c8dee2aaSAndroid Build Coastguard Worker<meta http-equiv="origin-trial" content="ArQyw1ckz8lMOAcs5BbhOVJh2A6KMhYL6w/rTjPNnViqZyfFhlyJ5hnuHARoCkS1ZKiJi+YbsFvPWy23ePkFMQgAAABJeyJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjgxMjMiLCJmZWF0dXJlIjoiV2ViR1BVIiwiZXhwaXJ5IjoxNjQzMTU1MTk5fQ=="> 15*c8dee2aaSAndroid Build Coastguard Worker 16*c8dee2aaSAndroid Build Coastguard Worker<style> 17*c8dee2aaSAndroid Build Coastguard Worker canvas { 18*c8dee2aaSAndroid Build Coastguard Worker border: 1px dashed grey; 19*c8dee2aaSAndroid Build Coastguard Worker } 20*c8dee2aaSAndroid Build Coastguard Worker</style> 21*c8dee2aaSAndroid Build Coastguard Worker 22*c8dee2aaSAndroid Build Coastguard Worker<body> 23*c8dee2aaSAndroid Build Coastguard Worker <h1>WebGPU Test</h1> 24*c8dee2aaSAndroid Build Coastguard Worker <pre id="log"></pre> 25*c8dee2aaSAndroid Build Coastguard Worker 26*c8dee2aaSAndroid Build Coastguard Worker <canvas id=draw width=500 height=500></canvas> 27*c8dee2aaSAndroid Build Coastguard Worker</body> 28*c8dee2aaSAndroid Build Coastguard Worker 29*c8dee2aaSAndroid Build Coastguard Worker<script type="text/javascript" charset="utf-8"> 30*c8dee2aaSAndroid Build Coastguard Worker if ("gpu" in navigator) { 31*c8dee2aaSAndroid Build Coastguard Worker log("WebGPU detected") 32*c8dee2aaSAndroid Build Coastguard Worker WebGPUDemo(); 33*c8dee2aaSAndroid Build Coastguard Worker } else { 34*c8dee2aaSAndroid Build Coastguard Worker log("No WebGPU support.") 35*c8dee2aaSAndroid Build Coastguard Worker } 36*c8dee2aaSAndroid Build Coastguard Worker 37*c8dee2aaSAndroid Build Coastguard Worker function log(s) { 38*c8dee2aaSAndroid Build Coastguard Worker document.getElementById("log").innerText = s; 39*c8dee2aaSAndroid Build Coastguard Worker } 40*c8dee2aaSAndroid Build Coastguard Worker 41*c8dee2aaSAndroid Build Coastguard Worker async function WebGPUDemo() { 42*c8dee2aaSAndroid Build Coastguard Worker // Adapted from https://github.com/austinEng/webgpu-samples/blob/main/src/sample/helloTriangle/main.ts 43*c8dee2aaSAndroid Build Coastguard Worker const adapter = await navigator.gpu.requestAdapter(); 44*c8dee2aaSAndroid Build Coastguard Worker if (!adapter) { 45*c8dee2aaSAndroid Build Coastguard Worker log("Could not load an adapter. For Chrome, try running with --enable-features=Vulkan --enable-unsafe-webgpu"); 46*c8dee2aaSAndroid Build Coastguard Worker return; 47*c8dee2aaSAndroid Build Coastguard Worker } 48*c8dee2aaSAndroid Build Coastguard Worker 49*c8dee2aaSAndroid Build Coastguard Worker const device = await adapter.requestDevice(); 50*c8dee2aaSAndroid Build Coastguard Worker console.log(adapter, device); 51*c8dee2aaSAndroid Build Coastguard Worker const canvas = document.getElementById("draw"); 52*c8dee2aaSAndroid Build Coastguard Worker const context = canvas.getContext('webgpu'); 53*c8dee2aaSAndroid Build Coastguard Worker if (!context) { 54*c8dee2aaSAndroid Build Coastguard Worker log("Could not load webgpu context"); 55*c8dee2aaSAndroid Build Coastguard Worker return; 56*c8dee2aaSAndroid Build Coastguard Worker } 57*c8dee2aaSAndroid Build Coastguard Worker console.log(context); 58*c8dee2aaSAndroid Build Coastguard Worker 59*c8dee2aaSAndroid Build Coastguard Worker const devicePixelRatio = window.devicePixelRatio || 1; 60*c8dee2aaSAndroid Build Coastguard Worker const presentationSize = [ 61*c8dee2aaSAndroid Build Coastguard Worker canvas.clientWidth * devicePixelRatio, 62*c8dee2aaSAndroid Build Coastguard Worker canvas.clientHeight * devicePixelRatio, 63*c8dee2aaSAndroid Build Coastguard Worker ]; 64*c8dee2aaSAndroid Build Coastguard Worker const presentationFormat = context.getPreferredFormat(adapter); 65*c8dee2aaSAndroid Build Coastguard Worker 66*c8dee2aaSAndroid Build Coastguard Worker context.configure({ 67*c8dee2aaSAndroid Build Coastguard Worker device, 68*c8dee2aaSAndroid Build Coastguard Worker format: presentationFormat, 69*c8dee2aaSAndroid Build Coastguard Worker size: presentationSize, 70*c8dee2aaSAndroid Build Coastguard Worker }); 71*c8dee2aaSAndroid Build Coastguard Worker 72*c8dee2aaSAndroid Build Coastguard Worker const triangleVertWGSL = `[[stage(vertex)]] 73*c8dee2aaSAndroid Build Coastguard Workerfn main([[builtin(vertex_index)]] VertexIndex : u32) 74*c8dee2aaSAndroid Build Coastguard Worker -> [[builtin(position)]] vec4<f32> { 75*c8dee2aaSAndroid Build Coastguard Worker var pos = array<vec2<f32>, 3>( 76*c8dee2aaSAndroid Build Coastguard Worker vec2<f32>(0.0, 0.5), 77*c8dee2aaSAndroid Build Coastguard Worker vec2<f32>(-0.5, -0.5), 78*c8dee2aaSAndroid Build Coastguard Worker vec2<f32>(0.5, -0.5)); 79*c8dee2aaSAndroid Build Coastguard Worker 80*c8dee2aaSAndroid Build Coastguard Worker return vec4<f32>(pos[VertexIndex], 0.0, 1.0); 81*c8dee2aaSAndroid Build Coastguard Worker}`; 82*c8dee2aaSAndroid Build Coastguard Worker 83*c8dee2aaSAndroid Build Coastguard Worker const redFragWGSL = `[[stage(fragment)]] 84*c8dee2aaSAndroid Build Coastguard Workerfn main() -> [[location(0)]] vec4<f32> { 85*c8dee2aaSAndroid Build Coastguard Worker return vec4<f32>(1.0, 0.0, 0.0, 1.0); 86*c8dee2aaSAndroid Build Coastguard Worker}`; 87*c8dee2aaSAndroid Build Coastguard Worker 88*c8dee2aaSAndroid Build Coastguard Worker const pipeline = device.createRenderPipeline({ 89*c8dee2aaSAndroid Build Coastguard Worker vertex: { 90*c8dee2aaSAndroid Build Coastguard Worker module: device.createShaderModule({ 91*c8dee2aaSAndroid Build Coastguard Worker code: triangleVertWGSL, 92*c8dee2aaSAndroid Build Coastguard Worker }), 93*c8dee2aaSAndroid Build Coastguard Worker entryPoint: 'main', 94*c8dee2aaSAndroid Build Coastguard Worker }, 95*c8dee2aaSAndroid Build Coastguard Worker fragment: { 96*c8dee2aaSAndroid Build Coastguard Worker module: device.createShaderModule({ 97*c8dee2aaSAndroid Build Coastguard Worker code: redFragWGSL, 98*c8dee2aaSAndroid Build Coastguard Worker }), 99*c8dee2aaSAndroid Build Coastguard Worker entryPoint: 'main', 100*c8dee2aaSAndroid Build Coastguard Worker targets: [ 101*c8dee2aaSAndroid Build Coastguard Worker { 102*c8dee2aaSAndroid Build Coastguard Worker format: presentationFormat, 103*c8dee2aaSAndroid Build Coastguard Worker }, 104*c8dee2aaSAndroid Build Coastguard Worker ], 105*c8dee2aaSAndroid Build Coastguard Worker }, 106*c8dee2aaSAndroid Build Coastguard Worker primitive: { 107*c8dee2aaSAndroid Build Coastguard Worker topology: 'triangle-list', 108*c8dee2aaSAndroid Build Coastguard Worker }, 109*c8dee2aaSAndroid Build Coastguard Worker }); 110*c8dee2aaSAndroid Build Coastguard Worker 111*c8dee2aaSAndroid Build Coastguard Worker console.log(pipeline); 112*c8dee2aaSAndroid Build Coastguard Worker 113*c8dee2aaSAndroid Build Coastguard Worker const startTime = Date.now(); 114*c8dee2aaSAndroid Build Coastguard Worker function frame() { 115*c8dee2aaSAndroid Build Coastguard Worker const now = Date.now(); 116*c8dee2aaSAndroid Build Coastguard Worker const commandEncoder = device.createCommandEncoder(); 117*c8dee2aaSAndroid Build Coastguard Worker const textureView = context.getCurrentTexture().createView(); 118*c8dee2aaSAndroid Build Coastguard Worker 119*c8dee2aaSAndroid Build Coastguard Worker const renderPassDescriptor = { 120*c8dee2aaSAndroid Build Coastguard Worker colorAttachments: [ 121*c8dee2aaSAndroid Build Coastguard Worker { 122*c8dee2aaSAndroid Build Coastguard Worker view: textureView, 123*c8dee2aaSAndroid Build Coastguard Worker loadValue: { 124*c8dee2aaSAndroid Build Coastguard Worker r: Math.abs(Math.sin((startTime - now) / 500)), 125*c8dee2aaSAndroid Build Coastguard Worker g: Math.abs(Math.sin((startTime - now) / 600)), 126*c8dee2aaSAndroid Build Coastguard Worker b: Math.abs(Math.sin((startTime - now) / 700)), 127*c8dee2aaSAndroid Build Coastguard Worker a: 1.0 }, 128*c8dee2aaSAndroid Build Coastguard Worker storeOp: 'store', 129*c8dee2aaSAndroid Build Coastguard Worker }, 130*c8dee2aaSAndroid Build Coastguard Worker ], 131*c8dee2aaSAndroid Build Coastguard Worker }; 132*c8dee2aaSAndroid Build Coastguard Worker 133*c8dee2aaSAndroid Build Coastguard Worker const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); 134*c8dee2aaSAndroid Build Coastguard Worker passEncoder.setPipeline(pipeline); 135*c8dee2aaSAndroid Build Coastguard Worker passEncoder.draw(3, 1, 0, 0); 136*c8dee2aaSAndroid Build Coastguard Worker passEncoder.endPass(); 137*c8dee2aaSAndroid Build Coastguard Worker 138*c8dee2aaSAndroid Build Coastguard Worker device.queue.submit([commandEncoder.finish()]); 139*c8dee2aaSAndroid Build Coastguard Worker requestAnimationFrame(frame); 140*c8dee2aaSAndroid Build Coastguard Worker } 141*c8dee2aaSAndroid Build Coastguard Worker 142*c8dee2aaSAndroid Build Coastguard Worker requestAnimationFrame(frame); 143*c8dee2aaSAndroid Build Coastguard Worker } 144*c8dee2aaSAndroid Build Coastguard Worker</script>