GPU Gems 2 · Chapter 5. Optimizing Resource Management with Multistreaming

用 G、T、A、I 四类 vertex stream 拆分几何、纹理、动画和实例数据,再由资源管理器按渲染 pass 只绑定当前需要的组件。

学习目标

  • 能把 mesh 的 geometry、texture、animation、instance 数据拆成职责清晰的 vertex stream
  • 能按 z-pass、纹理、动画和实例化等渲染 pass 选择最小 stream 组合
  • 能解释硬件无关的 mesh resource、Vertexprocessor 与硬件相关 vertex buffer 之间的边界
  • 能用实验识别“需要的 stream 超出硬件上限”时应该降级效果而不是读取缺失字段

现代 mesh 的一个顶点往往包含 position、normal、颜色、多个 UV、切线和骨骼权重,但一个具体 pass 通常只读取其中一部分。若每次绘制都传输完整顶点,系统会为没有被读取的数据支付内存和带宽成本。

Vertex streams:把一份胖顶点拆成四类职责GGeometrypositionnormalTTextureUVtangentAAnimationweightsinfluencesIInstancetransformfrequency同一 mesh 可按当前 pass 组合 G、T、A、I,而不是每次传输全部字段
先按更新频率和渲染职责拆分数据,再按 pass 选择需要绑定的 stream。

1. 用职责拆分 vertex stream

保存 geometry data,是大多数 pass 的基础。只在需要纹理或切线空间效果时加入。

服务硬件 skinning。服务实例化。它们的拆分让“动画开关”和“实例化开关”不必改变基础几何 stream 的布局。

Pass → stream combination渲染任务无纹理带纹理带宽Solid / colorGG + TAnimatedG + AG + T + AInstancedG + IG + T + IPure z-passGG + A / I最低G-stream 可用于快速 z-pass;复杂 pass 再加入必要的附加数据
pass 先决定需要哪些顶点字段;资源管理器据此绑定最小的 stream 集合。

组合不是越多越好。每增加一个 active stream,就增加绑定、声明和访存复杂度,因此应该从当前 shader 的输入反推最小集合:solid 可能是 G 加 T,纯 z-pass 甚至只需要 G,instanced mesh 再加入 I。

2. 资源管理器与 Vertexprocessor

可以用文件名或全局 ID 查询,并用引用计数让同一份 mesh 被多个场景对象复用。它保存的是 position、normal、UV、weights 等逻辑数组,而不是某个 GPU 的最终 stride。

在需要绘制时读取 MeshResource,决定当前顶点格式,过滤不需要的字段,并生成 G、T、A、I 等硬件相关 buffer。这个边界让同一套内容能适配不同设备和效果开关。

Resource manager → Vertexprocessor → GPU streamsMeshResource通用数组 + 引用计数位置 / 法线 / UV / 权重Vertexprocessor按 FVF / layout 分流按 pass 省略字段适配硬件容量G-streamT-streamA-streamI-stream资源管理关注生命周期,renderer 关注当前绘制所需的数据形状
mesh resource 保持 API 无关;Vertexprocessor 针对当前 GPU 生成所需布局。

生成后的 stream 可以缓存并复用;当资源尚未加载时再按需读取,已经加载时只增加引用。索引也应该选择足够而不过大的类型:顶点数量允许时使用较小索引能减少内存,但不能为了节省几个字节而溢出索引范围。

3. 带宽预算与效果降级

只传当前需要的 vertex components胖顶点positionnormalUV 0–7tangentweightscolors每个 pass 都付全量成本按 pass 选择positionnormalUV 0z-pass 甚至只需 G带宽随需求下降
删除当前效果不读取的 texture coordinates 或 animation data,可同时降低显存占用和总线传输。

“不传用不到的数据”有两层收益:显存中的 stream 更小,系统内存到 GPU 的传输也更少。硬件能力更弱时,关闭某个效果意味着它对应的 UV、切线或动画字段也可以从这条路径移除,而不是保留一份永远不会被读取的冗余布局。

同时要注意 multistreaming 不是免费的抽象。硬件有 MaxStreams 之类的能力上限,active stream 太多会带来绑定和访存开销。工程上应把常用组合控制在较小数量,并让资源管理器把能力检查与 fallback 变成明确的策略。

4. 动手实验:pass 决定输入

切换不同 pass,观察 G、T、A、I 哪些 stream 被绑定。再把可用 stream 数量调低,问自己:是关闭某个效果,还是继续绑定一个不完整的 stream?正确的答案应该由 shader 输入和硬件能力共同决定。

Multistreaming 实验

切换 pass,观察 renderer 绑定的最小 stream 集合。

InstancedGboundTboundAskipIbound加入逐实例数据,几何仍共享。active streams: G + T + I硬件可用 stream 数量:4

当前绑定 3 / 需要 3 个 stream。硬件上限不足时,应降级效果或拆分路径,而不是假装字段存在。

实验只模拟声明和绑定,不模拟真实 DMA 时间;它的目标是建立资源布局的决策顺序:先确定 pass,再选择字段,再检查能力,最后生成硬件声明。

小结

  • G、T、A、I 分别承担几何、纹理、动画和实例数据。
  • multistreaming 让不同 pass 只绑定实际需要的 vertex components。
  • MeshResource 保持硬件无关,Vertexprocessor 负责按 pass 和设备生成布局。
  • 少传字段可降低显存和带宽,但 active stream 数量也有硬件与性能边界。
  • 能力不足时应显式降级效果,不能让 shader 假设不存在的 stream。

练习

问题 1|组合 pass 为纯 z-pass、带纹理的静态 mesh、带动画的纹理 mesh 分别选择最小 stream 组合。

问题 2|架构边界 为什么 MeshResource 不应该直接保存某个 GPU 的最终 vertex declaration?

问题 3|能力不足 一个 instanced pass 需要 G、T、I,但设备只允许两个 active stream。你会怎么处理?

名词解释

本章出现的专业名词,用大白话再讲一遍。

G-stream
承载位置、法线和颜色等基础几何字段的 stream。
T-stream
承载 UV、切线和表面采样字段的 stream。
A-stream
承载骨骼权重与影响等动画字段的 stream。
I-stream
承载逐实例数据和实例化字段的 stream。
MeshResource
硬件无关的通用 mesh 数据与资源引用容器。
Vertexprocessor
将通用 mesh 翻译成当前 pass 和硬件所需 stream 布局的处理器。

讨论

评论区加载中…