DescriptorSet
2023-10-25 20:27:41 3 举报
AI智能生成
Vulkan DescriptorSet
作者其他创作
大纲/内容
Descriptor
定义
内容
类比为一个结构体,描述GPU上使用的各种资源的信息
信息
资源类型(Buffer/Image/Sampler)
大小
子类型
内存地址
...
位置
GPU Memory
Buffer相关
多个Descriptor可以指向同一个Buffer的不同位置
Descriptor Set
定义
内容
一系列Descriptor组成的集合
大小限制
16-64 bytes
作用
在dispatch shader的时候,通过指定descriptor set指针来说明shader可以访问哪些内存
一个pipeline可以绑定的descriptor set的指针是有限的(VkPhysicalDeviceLimits.maxBoundDescriptorSets)
Allocate
从Descriptor Pool中分配
关联Descriptor和Buffer(描述Set里面的每一个Descriptor都是指向哪个资源)
指定VkDescriptorBufferInfo
填充VkWriteDescriptorSet
指定DescritorSet
指定Buffer/Image等资源信息
vkUpdateDescriptorSets
背后会生成GPU command将GPU的寄存器设置为descriptor set的指针
Dynamic Descriptor Set
定义
复用Descriptor Set,通过vkCmdBindDescriptorSets时指定Offset来指定需要访问Buffer的哪块区域
优势
1. 避免频繁申请销毁Descriptor Set,从而降低了CPU负载
2. 相比HardCode offset(只能在初始化时VkWriteDescriptorSet指定Offset),Dynamic Descriptor Set可以每帧调整Offset
3. 允许你Bind一个Buffer指定Offset的区域,GPU使用这块区域渲染时,CPU侧同时往Buffer的其他区域写入
劣势
1. 因为要使用Offset来访问Buffer,而GPU并不能从任意位置开始读取,导致需要仔细地控制alignment
2. 相比hardcode offset, dynamic descriptor set要慢一点点(一般可忽略)
使用场景
适合
每个object都需要bind的数据
不适合
只需要每帧bind一次的数据(如camera)
使用注意事项
1. 创建DescriptorPool时指定VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
2. 创建VkDescriptorSetLayoutBinding时指定VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
3. vkUpdateDescriptorSets时指定VkWriteDescriptorSet
指定VkDescriptorBufferInfo
不使用HardCoded Offset
指定类型为VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
4. vkCmdBindDescriptorSets时指定Offset
Descriptor Pool
定义
Descriptor的内存池
分配方式
线性分配器 [推荐]
优势
只需要根据DescriptorSetLayout来给每个资源类型增加index就行了,效率高
劣势
不支持Free Individual Descriptor Set,一但vkResetDescriptorPool,整个Pool都清空
可配置项
各类资源的数量上限
能够分配的DescriptorSet上限
分配粒度
Descriptor Set
使用方式
通过指定DescriptorSetLayout告知内存布局
建议
如果不允许单独释放某个Set(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)那么申请/释放会快很多
一般对于Global descriptor set这么处理,申请一次,每帧重复使用
限制
一个Descriptor Pool同时只能被一个线程使用
使用流程[以Buffer资源为例]
1. Allocate Buffer(VMA,CPU_TO_GPU)
2. 创建DescriptorSetLayout描述DescriptorSet的布局
组成:VkDescriptorSetLayoutBinding
3. 修改VkPipelineLayout,描述Pipeline需要几个、什么样的DescriptorSetLayout
4. 创建VkDescriptorPool用于分配Descriptor
5. 分配DescriptorSet
指定使用哪个pool
指定创建几个Set
指定每一个Set的Layout
6. 关联Descriptor和Buffer(描述Set里面的每一个Descriptor都是指向哪个资源)
7. Draw Frame
往Buffer写入数据
绑定DescriptorSet
vkCmdBindDescriptorSets
DrawCall
最佳实践
Descriptor Set管理
基本策略[Free List of Pools]
1. 需要时从Free List中取一个Pool
2. 当前Pool用完了从List中取一个新的Pool
3. Descriptor使用完成后(Frame结束),ResetPool
4. Reset后的Pool归还给Free List
Pool Size设置策略
平均法
1. 统计一个场景需要的descriptor set和descriptor数量
2. 计算单个descriptor set的平均descriptor数量
3. 按照上述descriptor per descriptor set比例设置Pool大小
4. 一个Pool用完(如:1024个Set)后分配一个新的Pool
分级法
按照pipeline objects类型分别设置Pool
Shadow/Depth Pass
DrawPass
Descriptor Set类型选择
收藏
0 条评论
下一页