Cocos Creator:UBO 内存布局策略

推荐:将NSDT场景编辑器加入你的3D工具链
3D工具集:NSDT简石数字孪生

UBO 内存布局策略

Cocos Shader 规定,所有非 sampler 类型的 uniform 都应以 UBO(Uniform Buffer Object/Uniform Block)形式声明。

以内置着色器 builtin-standard.effect 为例,其 uniform block 声明如下:

uniform Constants {
    vec4 tilingOffset;
    vec4 albedo;
    vec4 albedoScaleAndCutoff;
    vec4 pbrParams;
    vec4 miscParams;
    vec4 emissive;
    vec4 emissiveScaleParam;
  };

并且所有的 UBO 应当遵守以下规则:

  1. 不应出现 vec3 成员;
  2. 对数组类型成员,每个元素 size 不能小于 vec4;
  3. 不允许任何会引入 padding 的成员声明顺序。

Cocos Shader 在编译时会对上述规则进行检查,以便在导入错误(implicit padding 相关)时及时提醒修改。

这可能听起来有些过分严格,但背后有非常务实的考量:
首先,UBO 是渲染管线内要做到高效数据复用的唯一基本单位,离散声明已不是一个选项;
其次,WebGL2 的 UBO 只支持 std140 布局,它遵守一套比较原始的 padding 规则:

所有 vec3 成员都会补齐至 vec4:

uniform ControversialType {
  vec3 v3_1; // offset 0, length 16 [IMPLICIT PADDING!]
}; // total of 16 bytes

任意长度小于 vec4 类型的数组和结构体,都会将元素补齐至 vec4:

uniform ProblematicArrays {
  float f4_1[4]; // offset 0, stride 16, length 64 [IMPLICIT PADDING!]
}; // total of 64 bytes

所有成员在 UBO 内的实际偏移都会按自身所占字节数对齐:

uniform IncorrectUBOOrder {
  float f1_1; // offset 0, length 4 (aligned to 4 bytes)
  vec2 v2; // offset 8, length 8 (aligned to 8 bytes) [IMPLICIT PADDING!]
  float f1_2; // offset 16, length 4 (aligned to 4 bytes)
}; // total of 32 bytes

uniform CorrectUBOOrder {
  float f1_1; // offset 0, length 4 (aligned to 4 bytes)
  float f1_2; // offset 4, length 4 (aligned to 4 bytes)
  vec2 v2; // offset 8, length 8 (aligned to 8 bytes)
}; // total of 16 bytes

这意味着大量的空间浪费,且某些设备的驱动实现也并不完全符合此标准,因此目前 Cocos Shader 选择限制这部分功能的使用,以帮助排除一部分非常隐晦的运行时问题。

3D建模学习工作室 翻译整理,转载请注明出处!

上一篇:Cocos Creator:自定义几何体实例化属性 (mvrlink.com)

下一篇:Cocos Creator:WebGL 1.0 向下兼容支持 (mvrlink.com)

NSDT场景编辑器 | NSDT 数字孪生 | GLTF在线编辑器 | 3D模型在线转换 | UnrealSynth虚幻合成数据生成器 | 3D模型自动纹理化工具
2023 power by nsdt©鄂ICP备2023000829号