跳到主要内容

WGSL 能力

本页介绍依赖设备支持的可选 WGSL 功能。引擎通过 device.supports* 标志及对应 CAPS_* 预处理宏公布能力,并在适用时向生成的 WGSL 注入所需 enable …; / requires …;。这些功能适用于顶点、片元和计算着色器。

半精度类型​

设备支持 16 位浮点运算(device.supportsShaderF16)时,可使用 WGSL 原生半精度类型,提高性能并降低内存带宽:

原生 WGSL 类型说明
f1616 位浮点标量
vec2h, vec3h, vec4h16 位浮点向量
mat2x2h, mat3x3h, mat4x4h16 位浮点矩阵

为方便使用,PlayCanvas 提供类型别名,支持时自动解析为 f16,不支持时回退到 f32:

别名支持 f16不支持 f16
halff16f32
half2vec2<f16>vec2f
half3vec3<f16>vec3f
half4vec4<f16>vec4f
half2x2mat2x2<f16>mat2x2f
half3x3mat3x3<f16>mat3x3f
half4x4mat4x4<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 指令之间的顺序不限。