WebGPU 现已在 Safari 技术预览版中开放测试
WebGPU 是一个新的符合标准的 API,它能在 Web 上实现高性能 3D 图形和通用计算。WebGPU 程序用 JavaScript 编写,但暴露了 GPU 功能,首次允许在 Web 内容中使用 GPU 计算。从 Safari 技术预览版 185 开始,WebGPU 可以被启用用于早期测试和开发。
要启用 WebGPU,请在 Safari 偏好设置的功能标志标签页中,打开“WebGPU”、“GPU 进程:DOM 渲染”和“GPU 进程:Canvas 渲染”功能标志。如果您没有看到功能标志标签页,您需要先在“高级”标签页中勾选“显示网页开发者功能”。
在 Safari 技术预览版 185 中启用 WebGPU 后,请尝试这个 WebGPU 示例。它利用了 WebGPU 的许多最佳功能。
WebGPU JavaScript API
WebGPU API 通过 JavaScript 访问,类似于 WebGL。
创建 GPUDevice
为了使用 WebGPU,必须创建一个设备。资源和管道状态是从 GPUDevice
实例创建的。要创建一个具有默认限制和在所有支持 WebGPU 的设备上都支持的功能的设备,我们可以向 requestAdapter
和 requestDevice
的调用传递零参数。
const adapter = await navigator.gpu.requestAdapter();
device = await adapter.requestDevice();
配置 GPUCanvasContext
GPUCanvasContext
是一个接口,允许您配置内容在页面上相应的 HTMLCanvas
元素中显示的方式。
context = canvas.getContext('webgpu');
const canvasFormat = "bgra8unorm";
const contextConfiguration = {
device: device,
format: canvasFormat,
alphaMode: 'opaque',
};
context.configure(contextConfiguration);
创建 GPURenderPipeline
GPURenderPipeline
或相应的 GPUComputePipeline
用于配置图形驱动程序的管道状态。然后,此管道状态会在 GPURenderPassEncoder
或 GPUComputePassEncoder
中使用,如下面所示。
const shaderModule = device.createShaderModule({ code: wgslSource });
const vertexStageDescriptor = { module: shaderModule, entryPoint: "vsmain" };
const fragmentStageDescriptor = { module: shaderModule, entryPoint: "fsmain" };
const renderPipelineDescriptor = {
layout: 'auto',
vertex: vertexStageDescriptor,
fragment: fragmentStageDescriptor,
primitive: {topology: "triangle-list" },
};
const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor);
发出绘制调用
创建 GPURenderPassEncoder
以向图形驱动程序发送绘制调用。在下面的示例中,我们绘制一个包含三个顶点的简单三角形。GPURenderPassEncoder
还可以绘制同一几何体的多个实例或从顶点缓冲区的偏移量处绘制。
const colorAttachmentDescriptor = {
view: renderAttachment,
loadOp: "clear",
storeOp: "store",
clearColor: { r: 0.15, g: 0.15, b: 0.5, a: 1 }
};
const renderPassDescriptor = { colorAttachments: [colorAttachmentDescriptor] };
const commandEncoder = device.createCommandEncoder();
const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
renderPassEncoder.setPipeline(renderPipeline);
const vertexBufferSlot = 0;
renderPassEncoder.setVertexBuffer(vertexBufferSlot, vertexBuffer, 0);
renderPassEncoder.draw(3, 1, 0, 0); // 3 vertices, 1 instance, 0th vertex, 0th instance.
renderPassEncoder.end();
const commandBuffer = commandEncoder.finish();
const queue = device.queue;
queue.submit([commandBuffer]);
WebGPU 着色语言
WebGPU 引入了 WGSL,一种适用于 Web 的平台独立着色语言。以下是一个 WGSL 着色器源代码的示例,它将替代上述 API 调用中的 wgslSource
。
const wgslSource = `
struct Vertex {
@builtin(position) Position: vec4<f32>,
@location(0) color: vec4<f32>,
}
@vertex fn vsmain(@builtin(vertex_index) VertexIndex: u32) -> Vertex
{
var pos: array<vec2<f32>, 3> = array<vec2<f32>, 3>(
vec2<f32>( 0.0, 0.5),
vec2<f32>(-0.5, -0.5),
vec2<f32>( 0.5, -0.5));
var vertex_out : Vertex;
vertex_out.Position = vec4<f32>(pos[VertexIndex], 0.0, 1.0);
vertex_out.color = vec4<f32>(pos[VertexIndex] + vec2<f32>(0.5, 0.5), 0.0, 1.0);
return vertex_out;
}
@fragment fn fsmain(in: Vertex) -> @location(0) vec4<f32>
{
return in.color;
}
`;
尝试 WebGPU 并提交错误!
我们很高兴在最新版 Safari 技术预览版中提供了 WebGPU 和 WGSL 的早期版本。请务必尝试一下。查看 WebGPU 示例的公共仓库。并在 bugs.webkit.org 提交您发现的错误或问题。