系列博客总目录:https://segmentfault.com/a/1190000040716735


WebGPU 基本概念节选翻译,选自 WebGPU Spec 3 Fundamentals,本文列举一部分简单的内容,其余内容以后单独拉出去和其他资料一起谈。

1 公共约定

节选自 WebGPU Spec 3.1 Conventions

① WebGPU 接口

WebGPU 接口是内部对象的公开访问形式,和大多数语言的接口语法提供的功能差不多。

这里只需注意,继承了 GPUObjectBase 的接口都是 WebGPU 接口。

interface mixin GPUObjectBase {
  attribute USVString? label;
};

label 字段用来描述对象自身,可空。

② 对象描述者

对象描述者包含创建一个对象所需的信息,通常调用 GPUDevicecreateXXX 方法完成。

dictionary GPUObjectDescriptorBase {
  USVString label;
};

此处的 label 和 GPUObjectBase 的 label 含义差不多。

2 坐标系统

节选自 WebGPU Spec 3.3 Coordinate Systems

  • 在 NDC 中,Y轴朝上。NDC的点 (-1.0, -1.0) 位于 NDC 的左下角。NDC的 X 和 Y 的最大最小值为 1 和 -1,Z 的取值范围是 [0, 1]。NDC 中超出此范围的点会被剪裁。
  • 在 Framebuffer、视口坐标系和 Fragment/像素坐标系中 Y轴朝下。原点 (0, 0) 位于这几个坐标系的左上角。
  • 视窗坐标和帧缓存(Framebuffer)坐标相匹配。
  • 纹理坐标的原点 (0, 0) 表示纹理数据的第一个纹素(texel)。

WebGPU 的坐标系和 DirectX 坐标系匹配。

3 核心对象

节选自 WebGPU Spec 3.5 Core Internal Objects

Adapter(适配器)

适配器对象表示 WebGPU 在具体系统中现代图形接口的实现。如果适配器对象变得不可用了,那就会被标记为无效,并且永远不会再变有效,并且,连带着由它创建的设备等对象一并变得无效。

适配器对象可以简单理解为图形处理器,既可以是真的物理显卡,也可以是由模拟出来的的软显卡。不同的适配器对象允许指向同一个显卡,譬如适配器A和适配器B,只是在请求参数上略有不同。

适配器对象在 WebGPU 中由 GPUAdapter 接口实现。

关于适配器对象的请求与创建过程,参考初始化部分的内容。

Devices(设备)

设备是适配器的逻辑功能上的实现,所有的 WebGPU 子对象均由设备对象创建,它可以在专用型 WebWorker 中使用。

如果设备对象失效了,那么由设备对象创建的子对象也会变得不可用。

设备对象在 WebGPU 中由 GPUDevice 接口实现。

关于设备对象的请求与创建过程,参考初始化部分的内容。

4 WebGPU 的功能列表及其最大限制

节选自 WebGPU Spec 3.6 Optional Capabilities

4.2 功能

功能,指的是一组可选的 WebGPU 功能,并不是所有的平台都支持,通常是操作系统或者显卡硬件不支持。

每个 GPUAdapter 都会带有一个 features 对象,在请求设备对象时只能用这个对象内的功能,也只有在请求设备对象时,才能设置这个即将被创建的设备对象能有哪些功能。

有关 WebGPU 功能的具体描述,参考 WebGPU Spec 23. Feature Index 后列举如下:

译者注

有点蛋疼的是,你直接访问 adapter.features 它只是个类似 Set 的对象,而不是普通的对象能看到里面有什么支持的功能,要你自己去访问 values ...

① depth-clamping

启用这个功能时,GPUPrimitiveState 接口的 clampDepth 属性才能被设置:

const renderPipeline = device.createRenderPipeline({
  /*...*/,
  primitive: {
    /* ... */,
    clampDepth: true
  }
})

② depth24unorm-stencil8

启用这个功能时,才能创建 "depth24unorm-stencil8" 格式的纹理对象:

const texture = device.createTexture({
  /* ... */,
  format: "depth24unorm-stencil8"
})

③ depth32float-stencil8

启用这个功能时,才能创建 "depth32float-stencil8" 格式的纹理对象:

const texture = device.createTexture({
  /* ... */,
  format: "depth32float-stencil8"
})

④ pipeline-statistics-query

启用这个功能时,枚举类型 GPUQueryType 才能用。

⑤ texture-compression-bc

启用这个功能时,才能创建 BC 格式的纹理:

const texture = device.createTexture({
  /* ... */,
  format: "bc1-rgba-unorm" / "bc1-rgba-unorm-srgb" / "bc2-rgba-unorm" / "bc2-rgba-unorm-srgb" / "bc3-rgba-unorm" / "bc3-rgba-unorm-srgb" / "bc4-r-unorm" / "bc4-r-snorm" / "bc5-rg-unorm" / "bc5-rg-snorm" / "bc6h-rgb-ufloat" / "bc6h-rgb-float" / "bc7-rgba-unorm" / "bc7-rgba-unorm-srgb"
})

⑥ timestamp-query

启用这个功能后,枚举类型 GPUQueryType 中的 "timestamp" 枚举才能使用。

4.1 限制

每个限制属性的值类型都是数字。每个限制对象(适配器对象和设备对象的一个属性)上的限制属性个数都是一样的,区别就是他们的值有可能不太一样。

设备对象的限制优先级高于适配器的,因为大多时候用的是设备对象,而且设备对象是由适配器对象请求的,适配器对象请求设备对象的时候可以传递对设备对象的限制需求。

注意,每条限制要与硬件适配,不要在移动设备上把限制放得很宽,否则容易影响性能。合理的限制需要因具体硬件而定。

每条限制都有一个默认值,如果适配器在请求设备时,没有传递限制参数 requiredLimits,那么就会使用默认值。

现在,对限制值进行逐条解释。

限制名类型建议值默认值解释
maxTextureDimension1Dunsigned long可设更高8192创建一维纹理对象时,size 属性最大允许值
maxTextureDimension2Dunsigned long可设更高8192创建二维纹理对象时,size 属性最大允许值
maxTextureDimension3Dunsigned long可设更高8192创建三维纹理对象时,size 属性最大允许值
maxTextureArrayLayersunsigned long可设更高256GPUExtent3DDict 对象的 depthOrArrayLayers 属性的最大值
maxBindGroupsunsigned long可设更高4创建 GPUPipelineLayout 时,绑定组的布局对象数量(也即绑定组的最大个数)
maxDynamicUniformBuffersPerPipelineLayoutunsigned long可设更高8创建 GPUPipelineLayout 时,每个管线的布局对象中允许设置带有动态偏移值的 UBO 的最大数量
maxDynamicStorageBuffersPerPipelineLayoutunsigned long可设更高4创建 GPUPipelineLayout 时,每个管线的布局对象中允许设置带有动态偏移值的存储型 GPUBuffer 的最大数量
maxSampledTexturesPerShaderStageunsigned long可设更高16(在其可能用到的着色器阶段中)绑定组的布局对象中允许设置采样纹理的最大个数
maxStorageBuffersPerShaderStageunsigned long可设更高8(在其可能用到的着色器阶段中)绑定组的布局对象中允许设置的存储型 GPUBuffer 的最大个数
maxStorageTexturesPerShaderStageunsigned long可设更高4(在其可能用到的着色器阶段中)绑定组的布局对象中允许设置的存储型纹理的最大个数
maxUniformBuffersPerShaderStageunsigned long可设更高12(在其可能用到的着色器阶段中)绑定组的布局对象中允许设置的 UBO 的最大个数
maxUniformBufferBindingSizeunsigned longlong可设更高16384绑定组布局对象的 entry 中 UBO 的 size 属性的最大值
maxStorageBufferBindingSizeunsigned longlong可设更高13427728(128MB)绑定组布局对象的 entry 中存储型或只读存储型 (storageread-only-storage) GPUBuffer 的 size 属性的最大值
minUniformBufferOffsetAlignmentunsigned long尽量设小256绑定组布局对象的 entry 中 UBO 的 offset 值,以及 setBindGroup 方法的动态 offset 值,这是一个对齐值
minStorageBufferOffsetAlignmentunsigned long尽量设小256绑定组布局对象的 entry 中存储型或只读存储型 (storageread-only-storage) GPUBuffer 的 offset 值,以及 setBindGroup 方法的动态 offset 值,这是一个对齐值
maxVertexBuffersunsigned long可设更高8渲染管线能创建最大 VBO 的个数
maxVertexAttributesunsigned long可设更高16渲染管线中 VBO 的最大顶点属性个数
maxVertexBufferArrayStrideunsigned long可设更高2048渲染管线中 VBO 的最大字节偏移量
maxInterStageShaderComponentsunsigned long可设更高60不同渲染阶段通信时,在通信中传递的变量中允许的最大组件个数(例如顶点阶段到片元阶段)
maxComputeWorkgroupStorageSizeunsigned long可设更高16352计算着色器入口函数中工作组允许使用的最大空间(单位:字节)
maxComputeInvocationsPerWorkgroupunsigned long可设更高256计算着色器入口函数中 workgroup_size 乘积的最大值
maxComputeWorkgroupSizeXunsigned long可设更高256计算着色器入口函数中 workgroup_size 中 X 维度的最大值
maxComputeWorkgroupSizeYunsigned long可设更高256计算着色器入口函数中 workgroup_size 中 Y 维度的最大值
maxComputeWorkgroupSizeZunsigned long可设更高64计算着色器入口函数中 workgroup_size 中 Z 维度的最大值
maxComputeWorkgroupsPerDimensionunsigned long可设更高65535计算通道编码器的 dispatch(x, y, z) 函数参数中的最大值

4.1.1 GPUSupportedLimits

GPUSupportedLimits 接口暴露了适配器或者设备对象的最大限制,直接访问 device.limitsadapter.limits 即可,是一个对象。

[Exposed=(Window, DedicatedWorker)]
interface GPUSupportedLimits {
  readonly attribute unsigned long maxTextureDimension1D;
  readonly attribute unsigned long maxTextureDimension2D;
  readonly attribute unsigned long maxTextureDimension3D;
  readonly attribute unsigned long maxTextureArrayLayers;
  readonly attribute unsigned long maxBindGroups;
  readonly attribute unsigned long maxDynamicUniformBuffersPerPipelineLayout;
  readonly attribute unsigned long maxDynamicStorageBuffersPerPipelineLayout;
  readonly attribute unsigned long maxSampledTexturesPerShaderStage;
  readonly attribute unsigned long maxSamplersPerShaderStage;
  readonly attribute unsigned long maxStorageBuffersPerShaderStage;
  readonly attribute unsigned long maxStorageTexturesPerShaderStage;
  readonly attribute unsigned long maxUniformBuffersPerShaderStage;
  readonly attribute unsigned long long maxUniformBufferBindingSize;
  readonly attribute unsigned long long maxStorageBufferBindingSize;
  readonly attribute unsigned long minUniformBufferOffsetAlignment;
  readonly attribute unsigned long minStorageBufferOffsetAlignment;
  readonly attribute unsigned long maxVertexBuffers;
  readonly attribute unsigned long maxVertexAttributes;
  readonly attribute unsigned long maxVertexBufferArrayStride;
  readonly attribute unsigned long maxInterStageShaderComponents;
  readonly attribute unsigned long maxComputeWorkgroupStorageSize;
  readonly attribute unsigned long maxComputeInvocationsPerWorkgroup;
  readonly attribute unsigned long maxComputeWorkgroupSizeX;
  readonly attribute unsigned long maxComputeWorkgroupSizeY;
  readonly attribute unsigned long maxComputeWorkgroupSizeZ;
  readonly attribute unsigned long maxComputeWorkgroupsPerDimension;
};

每项的解释见上文。

4.1.2 GPUSupportedFeatures

GPUSupportedFeaturesdevice.featuresadapter.features 对象所实现的接口。

这个对象不是普通的 JavaScript 对象,而是类似 ES6 中 Set 一样的集合,你可以使用 has 方法来查看有什么功能。它只能添加 GPUFeatureName (定义在 WebGPU Spec 4.4.1.1 GPUFeatureName)枚举中的值。

[Exposed=(Window, DedicatedWorker)]
interface GPUSupportedFeatures {
    readonly setlike<DOMString>;
};

enum GPUFeatureName {
  "depth-clamping",
  "depth24unorm-stencil8",
  "depth32float-stencil8",
  "pipeline-statistics-query",
  "texture-compression-bc",
  "timestamp-query",
};

注意,GPUFeatureName 会慢慢添加,但是浏览器实现不一定就跟得上进度,这时候可以用判断优雅地解决:

if (adapter.features.has('unknown-feature')) {
  // Use unknown-feature
} else {
  console.warn('unknown-feature is not supported by this adapter.');
}

岭南灯火
83 声望55 粉丝

一介草民