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>