1. 获取高频操作对象
1.1 WebGL 获取上下文对象
WebGL 获取的是 WebGLRenderingContext/WebGLRenderingContext2
对象,必须依赖于有适合宽度和高度的 HTMLCanvasElement
,通常命名为 gl
,gl 变量有十分多办法,容许批改 WebGL 的全局状态
const gl = document.getElementById("id")?.getContext("webgl")
// ...
1.2 WebGPU 获取设施对象
而 WebGPU 则不依赖具体的 Canvas,它操作的是物理图形卡设施,并应用 ES6/7
的异步语法获取,获取的是 GPUAdapter
和 GPUDevice
,然而与 WebGLRenderingContext
起着相似“收回大多数命令”的大管家式角色的,更多是 GPUDevice
对象
const entryFn = async () => {if (!navigator.gpu) {return}
// 测试版 Chrome 有可能返回 null
const adapter = await navigator.gpu.requestAdapter()
if (!adapter) {return}
const device = await adapter.requestDevice()
// ...
}
entryFn()
WebGPU 的入口是 navigator.gpu
对象,这个对象在 WebWorker 中也有,所以对 CPU 端的多线程有良好的反对。应用此对象异步申请适配器后,再应用适配器申请具象化的设施对象即可。
至于“适配器”和“设施”的概念界定,须要读者自行浏览 WebGPU Explainer、WebGPU Specification Core Object 等材料,前者大略是物理设施的一个变量符号,而依据不同的场景、线程需要再次申请“设施”,此设施并非物理设施,只是一个满足代码上下文所须要条件的、更理论的“对象”。
每次申请的适配器对象是不同的,不具备单例特色。
设施对象用于创立 WebGPU 中简直所有的子类型,包含 GPUBuffer
、GPUTexture
等,以及拜访一些自有属性,例如队列属性 device.queue
.
2. 初始化参数的异同
2.1 WebGL
在 WebGLRenderingContext 时,容许传递一些参数:
const gl = canvasEle.getContext("webgl", {
alpha: false, // 是否蕴含透明度缓存区
antialias: false, // 是否开抗锯齿
depth: false, // 是否蕴含一个 16 位的深度缓冲区
stencil: false, // 是否蕴含一个 8 位的模板缓冲区
failIfMajorPerformanceCaveat: false, // 在零碎性能低的环境中是否创立上下文
powerPreference: "high-performance", // GPU 电源配置,"high-performance" 是高性能
preserveDrawingBuffer: false, // 是否保留缓冲区
premultipliedAlpha: false, // 是否预乘透明度通道
})
2.2 WebGPU 分两步
2.2.1 GPUAdapter
在申请 WebGPU 的适配器时,保留了性能选项(以后标准)powerPreference:
// in async function
const adapter = await navigator.gpu.requestAdapter({powerPreference: "high-performance",})
对于 requestAdapter 办法的参数,其类型 GPURequestAdapterOptions
定义,见下:
dictionary GPURequestAdapterOptions {
GPUPowerPreference powerPreference;
boolean forceFallbackAdapter = false;
};
enum GPUPowerPreference {
"low-power",
"high-performance",
};
forceFallbackAdapter
参数用得不多,有须要的读者可自行查问官网文档。
2.2.2 GPUDevice
申请设施对象时,则容许传入 GPUDeviceDescriptor
参数对象,该对象容许有两个可选参数,一个是 requiredFeatures
,类型为 string[]
,另一个是 requiredLimits
,类型是键为 string 值为 number 的对象:
dictionary GPUDeviceDescriptor : GPUObjectDescriptorBase {sequence<GPUFeatureName> requiredFeatures = [];
record<DOMString, GPUSize64> requiredLimits = {};};
requireFeatures 数组的元素是字符串,不是轻易填的,要参考 WebGPU Spec 24 性能索引表 中的性能。传递这个性能数组,就意味着要向适配器申请有这么多功能的设施对象;
requireLimits 则向图形处理器申请判断,我传递进来的这个要求,你能不能满足。
如果超过了适配器的 limits,那么申请将失败,适配器的 requestDevice 办法将返回一个 reject 的 Promise;
如果传入的限度条目标要求没有比全局默认值更好(有“更大更好”和“更小更好”,参考 WebGPU 第 3 章 中无关 limits 的表述),那就返回带默认值的设施对象,并 resolve Promise;
其中,限度条目有哪些,默认值是多少,对某个限度条目“更大值更好”还是“更小值更好”,要参考 WebGPU Spec 3.6 限度 中的表格。
下面这么说会比拟形象,上面举例说明。
例如上面这个例子,申请设施对象时,会问适配器能不能满足我要求的条件:
- 最多要有 2 个绑定组(默认是 4 个,越大越好,显然 2 < 4)
- 最多只能有 4 个 UBO(默认 12 个,越大越好,显然 4 < 12)
- 能不能满足 2048 像素尺寸的 2D 纹理(默认 8192 像素,越大越好,显然 2048 < 8192)
const device = await adapter.requestDevice({
maxBindGroups: 2,
maxUniformBuffersPerShaderStage: 4,
maxTextureDimension2D: 2048,
})
显然,申请的这三个条件都满足要求,返回的设施对象的限度列表都按所有限度条目标默认值来。
console.log(device.limits)
{
maxBindGroup: 4,
maxUniformBuffersPerShaderStage: 12,
maxTextureDimension2D: 8192,
// ...
}
对于这段,requiredLimits 的含意是“我的程序可能要这样的要求,你这个适配器能不能满足”,而不是“我要这么多要求,你给我返回一个这些参数的设施对象”。设施的创立过程,在 WebGPU Specification 的第 3 章,外围对象 – 设施中有详细描述。
3. 总结
WebGL 的申请参数包含了性能参数和性能参数,较为简单。
WebGPU 分成了两个阶段,申请适配器时能够对性能作要求,申请设施对象时能够对应用 GPU 时各个方面的参数作校验能不能满足程序要求。