Base-描述符与Bindless资源绑定
Shader 中的纹理名不是 CPU 对象地址。图形 API 需要一种方式说明“这个槽位对应哪块资源、按什么格式、怎样访问”。描述符就是这种绑定信息的一部分。
Bindless 把逐 Draw 设置少量资源的方式,扩展为预先准备较大的可索引集合,再由 Shader 用索引选择。它减少的是某些绑定工作,不会让资源管理、同步与采样成本消失。
1. 描述符与资源视图
一块纹理内存可以按不同视图解释。SRV、UAV、CBV、RTV/DSV 和 Sampler 的用途与约束不同,不应把所有描述符都理解为“存一个 GPU 地址”。
描述符可能包括格式、范围、维度和访问方式等信息。资源内存、视图描述和 Shader 可见的绑定位置,是需要分别维护的对象。
2. D3D12 Heap 与 Vulkan Pool 不等价
D3D12 的 Descriptor Heap 存放描述符;只有适当类型与标志的堆可供 Shader 可见。RTV/DSV 堆不按同样方式由 Shader 索引。
Vulkan 的 Descriptor Pool 则用于分配 Descriptor Set,不能把它看成 Shader 直接索引的 D3D12 Heap。Set、布局、更新方式与所用扩展共同决定绑定行为。
两套 API 都能实现灵活资源访问,但名称之间不是一一替换关系。
3. 按变化频率组织
相机参数每帧更新,材质纹理可能长期不变,对象索引可能每次绘制都变化。按频率组织数据,可以避免每次 Draw 重建整套描述。
静态描述符并不意味着纹理内容永远不变;它表示视图或绑定记录相对稳定。更新资源内容仍需要同步。动态描述符也不天然比静态方式省内存,峰值和回收策略同样重要。
4. Bindless 的索引链
1 | |
几何提交可以不再为每个对象切换一组固定纹理,GPU Driven 绘制也更容易从实例数据找到材质。但平台功能、数组容量、非一致索引规则与着色语言语义必须满足要求。
不同线程索引不同资源时,可能需要相应的 non-uniform 标记或扩展。编译通过不代表所有平台都按预期访问,也不代表访问完全相干。
5. 生命周期比索引更容易出错
CPU 认为槽位已经空闲时,GPU 可能仍有在途命令使用它。过早覆写描述符或释放资源,会让旧命令采到新对象或失效内存。
常见方式是按完成 Fence 延迟回收,使用每帧分配区、环形分配或带代次的句柄。槽位分配器必须记录“允许再次使用”的时间,而不只是一个空闲布尔值。
6. Bindless 还有哪些成本
大量资源常驻、不可预测索引、缓存工作集与纹理带宽仍然存在。传统材质排序可能改善局部性,使用大数组后也不能完全忽略材质和几何组织。
原笔记里的“几乎没有绑定成本”过于绝对。更准确的目标是减少 CPU 重复设置与提高批处理灵活性,然后测量描述符更新、提交和 GPU 采样是否真正改善。
总结
资源绑定是一套寻址与生命周期契约。描述符说明怎样访问,Bindless 扩大动态选择范围,分配器和同步则保证这些索引在 GPU 使用期间始终有效。少做绑定不等于少做所有管理。