11-stream-out

第 11 篇:Stream-Out

原文:Part 11

一句话定位

Stream-Out(OpenGL 中常称 Transform Feedback)把顶点/几何阶段的输出直接写入缓冲,使流水线中间结果可被后续 draw 或 CPU/其他阶段复用。

数据路径

flowchart LR VS[VS 输出] --> GS[可选 GS] GS --> R[后续光栅化] VS -.无 GS 时也可.-> SO[Stream-Out] GS --> SO SO --> B[内存缓冲] B --> D[后续 Draw / 间接输入 / 读回]

在某些 API 表达中,SO 被画在 GS 之后;这不代表必须执行一个真正 GS。驱动/硬件可让 VS 输出直接进入 SO,只需满足 API 对输出布局和顺序的规定。

为什么它不只是一次普通 store

SO 要把 shader 输出属性按声明布局写入一个或多个目标缓冲,并维护当前写指针、stride、边界和统计。若 GS 输出数量可变,实际写入大小直到运行时才知道。硬件还要处理:

  • 多 stream 或多 buffer 的分配;
  • primitive 完整性,避免空间不足时写出半个图元;
  • overflow 检测与查询统计;
  • 与光栅化并行消费同一输出时的扇出;
  • 后续把结果作为 vertex/index/indirect 数据读取时的可见性。

常见用途

  • 缓存蒙皮或其他昂贵顶点变换结果;
  • 粒子更新与几何反馈;
  • 捕获流水线中间数据用于调试;
  • 在早期 API/硬件上承担部分通用计算任务。

现代 compute 往往更灵活,但 SO 的顺序化输出和与图形流水线的直接连接仍有价值。

计数与间接执行

当输出数量由运行时决定,CPU 若先读回计数再发下一次 draw,会引入 GPU→CPU 同步停顿。更理想的路径是让 GPU 维护计数,并由后续间接 draw/dispatch 直接消费。读代码时要区分“数据缓冲”“写入计数/查询”“间接参数”是否为同一对象,以及它们之间插入何种 barrier。

术语对照

英文 中文理解 说明
Stream-Out 流输出 D3D 术语
Transform Feedback 变换反馈 OpenGL 近似对应概念
stream 输出流 GS 可将图元导向不同流
stride 步长 相邻输出记录间的字节距离
append counter 追加计数器 指示下一写入位置/输出数量
overflow 溢出 目标容量不足,需按 API 规则处理

面向 UMD/KMD 的阅读提示

  • 找 SO declaration 如何从 shader 输出 location/component 映射到 buffer offset。
  • 追踪 buffer 既作 SO target 又作 vertex source 时的 cache flush 与 hazard tracking。
  • 查询结果通常是异步写入;CPU 读取前需要等待,GPU 间接消费则可能只需设备侧 barrier。
  • KMD 负责 BO 与同步生命周期,不负责字段如何打包;字段布局属于 UMD/硬件 ABI。

自测与实验

  • 为什么输出缓冲剩余空间不足一个完整 primitive 时,不能简单写到末尾为止?
  • 用 CPU 读取 SO 计数再 draw,与 GPU indirect draw 相比,流水线停顿在哪里?
  • 若同一 pass 同时光栅化并 stream-out,输出扇出会增加哪些带宽和缓冲压力?

本篇总结

Stream-Out 将“流水线内部记录”变成“有布局、有计数、有同步语义的内存数据”,是理解 GPU 生产者—消费者链路的好例子。

posted @ 2026-10-26 21:59  Sailxiv  阅读(2)  评论(0)    收藏  举报