[demos] Add WebGPU demo using origin trial
Before we get too excited, this does not use CanvasKit. What this does add is an origin-trial token so we can more easily demo our progress on *.skia.org and test locally using localhost:8123 (which is the default if you run make local in //demos.skia.org) To view this locally, I started chrome (stable 94) with --enable-features=Vulkan --enable-unsafe-webgpu Enabling the Vulkan was the advice of https://web.dev/gpu/#browser-support The second flag make sure the whole stack also uses Vulkan. Change-Id: Ia1838352a46387b0b79e353601a32c859f6911c1 Bug: skia:12512 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/457316 Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
7fcda8e23e
commit
68365c7579
144
demos.skia.org/demos/webgpu/index.html
Normal file
144
demos.skia.org/demos/webgpu/index.html
Normal file
@ -0,0 +1,144 @@
|
||||
<!DOCTYPE html>
|
||||
<title>Web GPU Demo</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<!-- For *.skia.org https://developer.chrome.com/origintrials/#/registration/2983494015644598273
|
||||
Expires Nov 19, 2021
|
||||
-->
|
||||
<meta http-equiv="origin-trial" content="AnRs8mYss+Awd1DPUg2VfjXJbw2087/Dysaa3L7JmrbzTkwoEr87cX3y0zUfTGOFSLKJLRqNEmFAwfy+uumVXQsAAABbeyJvcmlnaW4iOiJodHRwczovL3NraWEub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJHUFUiLCJleHBpcnkiOjE2NDMxNTUxOTksImlzU3ViZG9tYWluIjp0cnVlfQ==">
|
||||
|
||||
<!-- For localhost:8123 https://developer.chrome.com/origintrials/#/registration/6568359319031513089
|
||||
Expires Nov 19, 2021
|
||||
-->
|
||||
<meta http-equiv="origin-trial" content="ArQyw1ckz8lMOAcs5BbhOVJh2A6KMhYL6w/rTjPNnViqZyfFhlyJ5hnuHARoCkS1ZKiJi+YbsFvPWy23ePkFMQgAAABJeyJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjgxMjMiLCJmZWF0dXJlIjoiV2ViR1BVIiwiZXhwaXJ5IjoxNjQzMTU1MTk5fQ==">
|
||||
|
||||
<style>
|
||||
canvas {
|
||||
border: 1px dashed grey;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<h1>WebGPU Test</h1>
|
||||
<pre id="log"></pre>
|
||||
|
||||
<canvas id=draw width=500 height=500></canvas>
|
||||
</body>
|
||||
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
if ("gpu" in navigator) {
|
||||
log("WebGPU detected")
|
||||
WebGPUDemo();
|
||||
} else {
|
||||
log("No WebGPU support.")
|
||||
}
|
||||
|
||||
function log(s) {
|
||||
document.getElementById("log").innerText = s;
|
||||
}
|
||||
|
||||
async function WebGPUDemo() {
|
||||
// Adapted from https://github.com/austinEng/webgpu-samples/blob/main/src/sample/helloTriangle/main.ts
|
||||
const adapter = await navigator.gpu.requestAdapter();
|
||||
if (!adapter) {
|
||||
log("Could not load an adapter. For Chrome, try running with --enable-features=Vulkan --enable-unsafe-webgpu");
|
||||
return;
|
||||
}
|
||||
|
||||
const device = await adapter.requestDevice();
|
||||
console.log(adapter, device);
|
||||
const canvas = document.getElementById("draw");
|
||||
const context = canvas.getContext('webgpu');
|
||||
if (!context) {
|
||||
log("Could not load webgpu context");
|
||||
return;
|
||||
}
|
||||
console.log(context);
|
||||
|
||||
const devicePixelRatio = window.devicePixelRatio || 1;
|
||||
const presentationSize = [
|
||||
canvas.clientWidth * devicePixelRatio,
|
||||
canvas.clientHeight * devicePixelRatio,
|
||||
];
|
||||
const presentationFormat = context.getPreferredFormat(adapter);
|
||||
|
||||
context.configure({
|
||||
device,
|
||||
format: presentationFormat,
|
||||
size: presentationSize,
|
||||
});
|
||||
|
||||
const triangleVertWGSL = `[[stage(vertex)]]
|
||||
fn main([[builtin(vertex_index)]] VertexIndex : u32)
|
||||
-> [[builtin(position)]] vec4<f32> {
|
||||
var pos = array<vec2<f32>, 3>(
|
||||
vec2<f32>(0.0, 0.5),
|
||||
vec2<f32>(-0.5, -0.5),
|
||||
vec2<f32>(0.5, -0.5));
|
||||
|
||||
return vec4<f32>(pos[VertexIndex], 0.0, 1.0);
|
||||
}`;
|
||||
|
||||
const redFragWGSL = `[[stage(fragment)]]
|
||||
fn main() -> [[location(0)]] vec4<f32> {
|
||||
return vec4<f32>(1.0, 0.0, 0.0, 1.0);
|
||||
}`;
|
||||
|
||||
const pipeline = device.createRenderPipeline({
|
||||
vertex: {
|
||||
module: device.createShaderModule({
|
||||
code: triangleVertWGSL,
|
||||
}),
|
||||
entryPoint: 'main',
|
||||
},
|
||||
fragment: {
|
||||
module: device.createShaderModule({
|
||||
code: redFragWGSL,
|
||||
}),
|
||||
entryPoint: 'main',
|
||||
targets: [
|
||||
{
|
||||
format: presentationFormat,
|
||||
},
|
||||
],
|
||||
},
|
||||
primitive: {
|
||||
topology: 'triangle-list',
|
||||
},
|
||||
});
|
||||
|
||||
console.log(pipeline);
|
||||
|
||||
const startTime = Date.now();
|
||||
function frame() {
|
||||
const now = Date.now();
|
||||
const commandEncoder = device.createCommandEncoder();
|
||||
const textureView = context.getCurrentTexture().createView();
|
||||
|
||||
const renderPassDescriptor = {
|
||||
colorAttachments: [
|
||||
{
|
||||
view: textureView,
|
||||
loadValue: {
|
||||
r: Math.abs(Math.sin((startTime - now) / 500)),
|
||||
g: Math.abs(Math.sin((startTime - now) / 600)),
|
||||
b: Math.abs(Math.sin((startTime - now) / 700)),
|
||||
a: 1.0 },
|
||||
storeOp: 'store',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
|
||||
passEncoder.setPipeline(pipeline);
|
||||
passEncoder.draw(3, 1, 0, 0);
|
||||
passEncoder.endPass();
|
||||
|
||||
device.queue.submit([commandEncoder.finish()]);
|
||||
requestAnimationFrame(frame);
|
||||
}
|
||||
|
||||
requestAnimationFrame(frame);
|
||||
}
|
||||
</script>
|
Loading…
Reference in New Issue
Block a user