04-texture-samplers
第 4 篇:纹理采样器(Texture Samplers)
原文:Part 4
一句话定位
纹理采样不是一次普通 load,而是一条由资源视图、采样状态、坐标、LOD、地址模式、过滤与格式解码共同决定的高延迟数据路径。
一次采样包含什么
flowchart LR
A[shader 坐标/梯度] --> B[LOD 与各向异性判断]
S[Sampler State] --> B
R[Resource View] --> C[地址与格式解释]
B --> C
C --> D[纹理缓存/内存请求]
D --> E[解压与格式转换]
E --> F[过滤与结果返回]
三类状态要分开
- 资源决定实际存储与布局,例如尺寸、mip 层、数组层和底层内存。
- 资源视图决定以什么格式和子资源范围解释同一份存储。
- 采样器状态决定寻址模式、min/mag/mip 过滤、LOD 限制、比较采样和各向异性等行为。
把它们分离可以复用资源,也让硬件描述符更紧凑;代价是驱动必须验证组合是否合法,并处理别名与读写冲突。
LOD、梯度与过滤
纹理坐标在屏幕上变化得越快,单个像素覆盖的纹理区域越大,越需要选择更低分辨率的 mip 以避免混叠。像素阶段通常由邻近 lane 的坐标差估计梯度;显式 LOD 或显式梯度指令则由 shader 提供选择依据。
双线性过滤会读取某一 mip 附近的多个 texel 并加权;三线性会在两个 mip 的过滤结果间再插值;各向异性过滤会针对狭长 footprint 取更多样本。API 中一个“sample”可能展开成多次地址计算、缓存访问与插值。
缓存与压缩
二维空间局部性使纹理缓存有效:相邻像素往往访问相邻 texel。纹理采用 tiled/swizzled 布局,也是为了让二维邻域落入较少缓存线和内存事务。块压缩纹理减少外部带宽;数据在靠近采样端的位置解压,再参与过滤。
缓存只能改善有局部性的访问。随机索引、极端放大/缩小、跨大范围的各向异性采样,都会提高缺失率与请求数。性能分析要同时看 shader 发出多少 sample、每个 sample 展开多少 texel、缓存命中和实际外部带宽。
术语对照
| 英文 | 中文理解 | 备注 |
|---|---|---|
| SRV / texture view | 纹理/资源视图 | 定义解释格式与子资源范围 |
| sampler state | 采样器状态 | 过滤、寻址、LOD 等 |
| mipmap | 多级渐远纹理 | 预过滤后的多分辨率层级 |
| derivative / gradient | 导数/梯度 | 用于估计屏幕像素的纹理 footprint |
| anisotropic filtering | 各向异性过滤 | 处理方向差异明显的 footprint |
| swizzle / tiling | 重排/分块布局 | 增强二维局部性,非线性行优先 |
面向 UMD/KMD 的阅读提示
- UMD:追踪 image/sampler descriptor 的构建,特别是 format、swizzle、mip offsets、tiling mode 与压缩元数据。
- 查 shader lowering:哪些采样操作变成目标 ISA 的 texture 指令,隐式梯度在哪些 shader stage 合法?
- KMD 通常不解释过滤语义,但必须保证纹理 BO、页表和压缩/辅助表在执行期间有效。
- 资源从 render target 转为 texture 时,检查是否需要 cache flush、layout transition、decompress/resolve;这类命令体现“上一个写者 → 下一个读者”的可见性关系。
自测与实验
- 为什么像素 shader 能自然获得隐式梯度,而计算 shader 通常需要显式 LOD/梯度?
- 同一存储建立不同格式视图时,哪些组合只改变解释,哪些可能触发不可兼容的压缩/布局限制?
- 用 GPU counter 比较顺序纹理访问和随机纹理访问,区分指令数量与 cache miss 的影响。
本篇总结
纹理单元是一条专门优化的“地址生成 + 缓存 + 解码 + 过滤”流水线;它省下 shader 指令,却仍受局部性和带宽支配。

浙公网安备 33010602011771号