阶段 5 · 进阶进阶24 分钟
动态偏移:一个大缓冲区服务多个对象
minUniformBufferOffsetAlignment 与 setBindGroup offsets
把多个对象的 uniform 块打包进一个缓冲区,绘制时用动态偏移选择当前对象。
LEARNING GOALS
先明确本课目标
1
查询 uniform 偏移对齐
2
声明 hasDynamicOffset
3
按对象切换偏移而不创建大量 BindGroup
MENTAL MODEL · 再建立心智模型
BindGroup 固定指向一段大资源,setBindGroup 的动态偏移像移动窗口,选择当前 draw 要看的子区间。
MINIMAL EXAMPLE
一个 BindGroup 怎样选择大 Buffer 中的不同对象?
动态偏移在 setBindGroup 时追加到 Buffer binding 的基础 offset,使同一 BindGroup 指向大 Buffer 内不同的对齐区间。
javascriptconst alignment = device.limits.minUniformBufferOffsetAlignment;
const stride = Math.ceil(objectBytes / alignment) * alignment;
pass.setBindGroup(0, objectGroup, [objectIndex * stride]);- 布局先开启 BindGroupLayout 的该 Buffer binding 必须设置 hasDynamicOffset: true。
- 偏移要对齐 Uniform 动态偏移必须满足 minUniformBufferOffsetAlignment。
- 范围不能越界 基础 offset + 动态 offset + binding size 必须落在 Buffer 内。
多个对象共享一个大 Uniform Buffer 和一个 BindGroup,绘制时只改变偏移数组。
OPTIONAL · 按需查阅完整术语表与概念边界遇到陌生术语时再展开,不打断主线实验。
展开⌄
能力协商GPUSupportedLimits纹理尺寸、绑定数量、缓冲区大小、工作组尺寸等可查询上限。内存布局Alignment数据字段、绑定偏移和复制行距必须满足的字节边界要求。错误对齐会导致验证失败或数据解释错误。资源管理Dynamic OffsetsetBindGroup 时附加的缓冲区子区间偏移,使一个 BindGroup 在大缓冲区内选择不同对象数据。资源管理Buffer Suballocation从少数大缓冲区切分小区域服务多个对象,减少资源数量和分配开销。内存布局minUniformBufferOffsetAlignment设备限制中 Uniform Buffer 动态偏移必须满足的最小字节对齐值,常见但不能硬编码为 256。资源绑定hasDynamicOffsetBindGroupLayout 缓冲区条目是否允许在 setBindGroup 时附加动态偏移的布尔声明。
LIVE EXPERIMENT · 先获得反馈
边改边运行
浏览器加载后会激活代码编辑器、独立运行环境与实时输出。
本课挑战
实现一个环形 uniform allocator。
回到原理,解释刚才发生了什么
先用结果建立反馈,再按运行流程、核心原理和知识关系逐层深入。
CORE IDEA
核心讲解
减少对象数量
成百上千个小 GPUBuffer 和 BindGroup 会增加管理成本。分配大缓冲区并切片可改善复用。
对齐是硬要求
每个动态偏移必须是设备 minUniformBufferOffsetAlignment 的倍数,常见值为 256,但必须查询。
OPTIONAL · 迁移时查阅WebGPU 与 WebGL2 对照主线实验完成后,再用完整映射处理跨平台或跨 API 迁移。
展开⌄
两者都能让一个大 UBO 服务多个对象;WebGPU 把动态偏移纳入布局契约。
WebGL
bindBufferRange 用 offset/size 把 UBO 子区间绑定到 uniform binding point。
WebGPU
BindGroup 固定大 Buffer,setBindGroup 时提供满足对齐要求的 dynamic offset。
两种 API 都必须查询而不是猜测对齐值;常见 256 不是跨平台保证。