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