WGSL 能力
本页介绍依赖设备支持的可选 WGSL 功能。引擎通过 device.supports* 标志及对应 CAPS_* 预处理宏公布能力,并在适用时向生成的 WGSL 注入所需 enable …; / requires …;。这些功能适用于顶点、片元和计算着色器。
半精度类型
设备支持 16 位浮点运算(device.supportsShaderF16)时,可使用 WGSL 原生半精度类型,提高性能并降低内存带宽:
| 原生 WGSL 类型 | 说明 |
|---|---|
f16 | 16 位浮点标量 |
vec2h, vec3h, vec4h | 16 位浮点向量 |
mat2x2h, mat3x3h, mat4x4h | 16 位浮点矩阵 |
为方便使用,PlayCanvas 提供类型别名,支持时自动解析为 f16,不支持时回退到 f32:
| 别名 | 支持 f16 | 不支持 f16 |
|---|---|---|
half | f16 | f32 |
half2 | vec2<f16> | vec2f |
half3 | vec3<f16> | vec3f |
half4 | vec4<f16> | vec4f |
half2x2 | mat2x2<f16> | mat2x2f |
half3x3 | mat3x3<f16> | mat3x3f |
half4x4 | mat4x4<f16> | mat4x4f |
这些别名自动包含在顶点和片元着色器中。计算着色器需通过 #include "halfTypesCS" 包含。
使用示例:
// Use half types for intermediate calculations
var color: half3 = half3(1.0, 0.5, 0.0);
var intensity: half = half(0.8);
var result: half3 = color * intensity;
// Convert back to f32 when needed (e.g., for output)
output.color = vec4f(vec3f(result), 1.0);
device.supportsShaderF16 为 true 时,引擎自动添加 enable f16; 并定义 CAPS_SHADER_F16 用于条件编译。WGSL 要求 f16 和 f32 显式转换,可用 half3(vec3fValue) 或 vec3f(half3Value) 在不同精度间转换。
诊断过滤器
并非所有可选 WGSL 指令都由设备能力控制。诊断过滤器属于核心 WGSL,而非扩展,因此没有 device.supports* 或 CAPS_*,引擎也不会注入它们。所有生成着色器中的 derivative_uniformity 因而保持默认的 error 严重性。
编译器无法证明调用位于一致控制流时,该规则会拒绝 dpdx / dpdy / fwidth、textureSample、textureSampleBias 和 textureSampleCompare。模块作用域指令可放宽要求:
diagnostic(off, derivative_uniformity);
浏览器支持不一致。上述模块指令均可解析,但 @diagnostic(…) 属性在 Safari 的函数和语句作用域,以及 Firefox 的语句作用域中会导致创建错误,因此不适合跨平台发布。目前也只有 Chrome 实际强制执行该规则。
抑制后的导数返回不确定值,而非正确值,因此只能作为最后手段。推荐修复方法和完整支持表参见导数与一致控制流。
WGSL 语言扩展
创建设备时,引擎读取 navigator.gpu.wgslLanguageFeatures,向生成的 WGSL 添加所需 enable …; 和 requires …;,以支持可选功能。源码可根据对应 CAPS_* 宏分支;在适用时,这些宏会与 Shader 定义中自有的 vertexDefines、fragmentDefines 和 cdefines 合并。
device.supportsShaderF16- 引擎注入:
enable f16; - 预处理宏:
CAPS_SHADER_F16 - **着色阶段:**顶点、片元和计算
- **详情:**本页的半精度类型,以及引擎
half/half2/ … 别名。
- 引擎注入:
device.supportsPrimitiveIndex- 引擎注入:
enable primitive_index; - 预处理宏:
CAPS_PRIMITIVE_INDEX - **着色阶段:**片元
- **详情:**设备支持时,简化 API 在
FragmentInput上提供primitiveIndex,并提供全局pcPrimitiveIndex。
- 引擎注入:
device.supportsDualSourceBlending- **引擎注入:**混合状态使用第二源因子的片元着色器变体会添加
enable dual_source_blending;。 - 预处理宏:
CAPS_DUAL_SOURCE_BLENDING - **着色阶段:**片元
- **详情:**提供用作混合因子的第二片元输出,参见双源混合。
- **引擎注入:**混合状态使用第二源因子的片元着色器变体会添加
device.supportsSubgroups- 引擎注入:
enable subgroups; - 预处理宏:
CAPS_SUBGROUPS - **着色阶段:**片元和计算
- **详情:**子组内置函数(
subgroupBroadcast、subgroupAdd等)。device.supportsSubgroupUniformity不添加独立的requires或enable,驱动会结合子组功能使用它。
- 引擎注入:
device.supportsSubgroupSizeControl- **引擎注入:**无。此功能依赖
device.supportsSubgroups,启用它时已添加enable subgroups;。使用@subgroup_size时,需自行添加enable subgroup_size_control;。 - 预处理宏:
CAPS_SUBGROUP_SIZE_CONTROL - **着色阶段:**计算
- **详情:**通过
@subgroup_size(N)将计算入口固定为指定子组大小;N必须是device.minSubgroupSize到device.maxSubgroupSize(均只读)范围内的 2 的幂。未指定时由驱动选择,无法预先知道。引擎只公布能力,enable由作者明确添加。参见 WebGPU 151–152 概览。
- **引擎注入:**无。此功能依赖
device.supportsSubgroupId- 引擎注入:
requires subgroup_id; - 预处理宏:
CAPS_SUBGROUP_ID - **着色阶段:**引擎将该着色器模块编译为 WGSL 的各阶段,通常为
Shader定义中的全部相关阶段。 - **详情:**工作组中的
subgroup_id和num_subgroups内置值。
- 引擎注入:
device.supportsLinearIndexing- 引擎注入:
requires linear_indexing;,仅用于计算模块入口,不用于顶点/片元。 - 预处理宏:
CAPS_LINEAR_INDEXING - **着色阶段:**计算
- 详情:
global_invocation_index和workgroup_index,参见 WebGPU 147–148 概览。
- 引擎注入:
device.supportsStorageTextureRead- **引擎注入:**无。读取存储纹理时,需自行添加
requires readonly_and_readwrite_storage_textures;。 - 预处理宏:
CAPS_STORAGE_TEXTURE_READ,设备能够读取存储纹理时设置,可用于共享代码路径。 - **着色阶段:**使用此功能的计算着色器。
- **详情:**引擎只公布能力,
requires由作者添加,以保持使用显式。
- **引擎注入:**无。读取存储纹理时,需自行添加
device.supportsUnrestrictedPointerParameters- 引擎注入:
requires unrestricted_pointer_parameters; - 预处理宏:
CAPS_UNRESTRICTED_POINTER_PARAMETERS - **着色阶段:**顶点、片元和计算
- **详情:**允许将
storage、uniform和workgroup地址空间的指针作为函数参数传递。
- 引擎注入:
device.supportsPointerCompositeAccess- 引擎注入:
requires pointer_composite_access; - 预处理宏:
CAPS_POINTER_COMPOSITE_ACCESS - **着色阶段:**顶点、片元和计算
- **详情:**复合类型指针解引用的语法糖,可写
p.field和p[i],代替(*p).field和(*p)[i]。
- 引擎注入:
device.supportsPacked4x8IntegerDotProduct- 引擎注入:
requires packed_4x8_integer_dot_product; - 预处理宏:
CAPS_PACKED_4X8_INTEGER_DOT_PRODUCT - **着色阶段:**顶点、片元和计算
- **详情:**提供 DP4a 系列内置函数(
dot4U8Packed、dot4I8Packed及pack4x{I,U}8、pack4x{I,U}8Clamp、unpack4x{I,U}8)用于 8 位打包整数点积,适合量化推理和大量整数计算。
- 引擎注入:
device.supportsTextureAndSamplerLet- 引擎注入:
requires texture_and_sampler_let; - 预处理宏:
CAPS_TEXTURE_AND_SAMPLER_LET - **着色阶段:**顶点、片元和计算
- **详情:**允许将纹理和采样器变量赋给
let绑定,为类似无绑定资源的间接寻址模式提供基础。
- 引擎注入:
计算示例:定义 CAPS_LINEAR_INDEXING 时使用线性工作组索引,否则回退到手动布局计算:
@compute @workgroup_size(64, 1, 1)
fn main(
@builtin(global_invocation_id) global_id: vec3u,
@builtin(num_workgroups) nwg: vec3u,
#ifdef CAPS_LINEAR_INDEXING
@builtin(workgroup_index) flat_wg: u32,
#endif
) {
#ifdef CAPS_LINEAR_INDEXING
let wg = flat_wg;
#else
let wg = global_id.x; // 1D dispatch; extend for 2D/3D as needed
#endif
_ = wg;
}
计算示例:定义 CAPS_SUBGROUP_SIZE_CONTROL 时固定子组大小,否则由驱动选择:
#ifdef CAPS_SUBGROUP_SIZE_CONTROL
enable subgroup_size_control; // enable subgroups; is already injected by the engine
#endif
@compute @workgroup_size(64)
#ifdef CAPS_SUBGROUP_SIZE_CONTROL
@subgroup_size(32) // power of two within device.minSubgroupSize..maxSubgroupSize
#endif
fn main(@builtin(global_invocation_id) global_id: vec3u) {
_ = global_id;
}
所有 enable …; 必须位于模块声明之前。引擎会将自身指令(例如 enable subgroups;)置于源码之前,因此你的 enable subgroup_size_control; 应放在代码块最顶部,早于任何 const、struct、var 或 fn。各 enable 指令之间的顺序不限。