Uniform Block 与 Shader Storage Buffer
| 特性 | Uniform Block (uniform) |
Shader Storage Buffer (buffer) |
|---|---|---|
| 设计用途 | 少量、高频更新的"参数" | 大量、任意大小的"数据" |
| 大小限制 | 很小 | 很大(可达显存上限) |
| 读写权限 | 只读 | 可读可写 |
| 布局规则 | 仅 std140 |
std430(默认) 或 std140 |
| 硬件存储位置 | 常量寄存器 / 专用 UBO Cache | 全局显存(走通用内存总线) |
| 访问速度 | 极快(专用硬件路径) | 较慢(通用内存访问,有缓存但延迟高) |
| 原子操作 | 不支持 | 支持 |
| 绑定数量 | 较少 | 较多 |
| 典型数据 | MVP矩阵、光照参数、材质属性 | 顶点/粒子数据、计算结果、大型查找表 |
- Uniform = “配置参数” 可以理解成函数的入参。数据量小、每帧可能变、所有着色器线程读同一份值。GPU 有专门的常量缓存来加速它,所以快,但也因此容量受限且只读。
- Buffer (SSBO) = “数据仓库” 可以理解成函数的堆内存指针。可以存任意大小的数据,着色器既能读也能写(包括原子操作),适合做 GPGPU 计算、粒子模拟、间接绘制命令等。代价是走通用显存总线,延迟比 UBO 高。
std430 与 std140 对齐差异
| 规则 | std140 | std430 |
|---|---|---|
| 数组元素对齐 | 一律按 vec4 (16B) | 按元素自身类型对齐(float=4, vec2=8, vec3=16…) |
| 结构体基对齐 | 一律按 vec4 (16B) | 取成员中最大对齐值(不再强制16) |
| 其他所有规则 | — | ⚠️ 与 std140 完全相同 |
std430 数组和结构体不再强制 vec4 对齐,改为"自然对齐",也只改了这两个。
SSBO(Shader Storage Buffer Object)
GLSL 声明
// 使用 std430 布局,绑定到 Binding Point 0
layout(std430, binding = 0) buffer ExampleBlock {
float a;
vec2 b;
vec3 c;
float d;
mat4 e;
} myData; // SSBO 通常建议给一个实例名,方便在 shader 中调用 myData.a创建 SSBO 并上传数据
GLuint ssbo;
glGenBuffers(1, &ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(ExampleBlock), &obj, GL_DYNAMIC_DRAW);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);绑定 SSBO
根据 Binding Point 绑定
// 绑定到 binding = 0
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);