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