Vulkan Material 设计学习

在学习 http://xiaopengyou.fun/public/2019/09/20/20_Material/ 的时候遇到的一些问题

初始化

初始化的时候 VkWriteDescriptorSet 把 ring buffer 绑定到 descriptor set

在每帧的最后,提交完 uniform buffer 的数据之后,vkCmdBindDescriptorSets 把 descriptor set 绑定到 command buffer

dynamicOffsetCount

其实他一开始是用 dynamicOffsetCount 来暂存计数值,他只是一个过程量,为了根据 set 和 binding 的顺序来设置 uniform buffer 的 offset 的索引的顺序

比如现在一个 shader 有四个 uniform buffer,那么

set = 0 binding = 0

set = 1 binding = 1

set = 0 binding = 1

set = 0 binding = 2

那么对应的 offset 的 index 为 0 3 1 2

但是之后他就拿 dynamicOffsetCount 当作 uniform buffer 的数量了

如果从一个独立的函数来看,突兀的出现这么一个量就让人困惑

其实最合适的就是在其他地方把他替换成 uniformBuffers.size()

有一个令我疑惑的问题

他有一个 vk_demo::DVKMaterial::BuffersMap vk_demo::DVKMaterial::uniformBuffers

SetLocalUniform 与 SetGlobalUniform

然后有三个函数 SetLocalUniform SetGlobalUniform SetStorageBuffer 都要从这个 map 中找对应的 buffer

SetLocalUniform 拿到数据指针之后,直接把数据存到 ring buffer,并且把存储到 ring buffer 的首地址存在 dynOffsets

SetGlobalUniform 拿到数据指针之后,却会把数据存在 uniformBuffers 这个 map 的 buffer 中

然后在 BeginFrame() 中,再把 SetGlobalUniformuniformBuffers 中存储的数据拿出来,存到 ring buffer

为什么是在 BeginFrame() 中拷贝 global uniform?为什么 global 暂存而非 global 的不暂存?

一开始我还觉得是不是多此一举,后来才明白不是

因为其实你每帧都在往 ring buffer 中写数据,而 global 的数据,不是在渲染主循环中提供的,而是只在初始化的时候提供一次

所以你需要暂存 global uniform buffer 的数据,而不用存 local 的

具体的可以看 BeginObject()

    void DVKMaterial::BeginObject()
    {
        int32 index = (int32)perObjectIndexes.size();
        perObjectIndexes.push_back(index);

        int32 offsetStart = index * dynamicOffsetCount;

        // 扩充dynamicOffsets尺寸以便能够保持每个Object的参数
        if (offsetStart + dynamicOffsetCount > dynamicOffsets.size())
        {
            // 因为每一次都是当前长度 + dynamicOffsetCount 来判断
            // 所以每一次增长的长度也是 dynamicOffsetCount
            // 就是实现了每次增加元素都是增加 dynamicOffsetCount 个元素
            for (uint32 i = 0; i < dynamicOffsetCount; ++i)
            {
                dynamicOffsets.push_back(0);
            }
        }

        // 拷贝GlobalOffsets
        // 但是 offsetIndex < dynamicOffsetCount 这里的终点是 dynamicOffsetCount
        // 那么其实只有 index = 0 的情况下这里才会被执行
        // 那么其实这里相当于 dynamicOffsets[0...dynamicOffsetCount-1] = globalOffsets[0...dynamicOffsetCount-1]
        // 应该改为 offsetIndex < offsetStart + dynamicOffsetCount?
        // 这个 globalOffsets 是只有一个 dynamicOffsetCount 的长度,因为全局的 uniform buffer 只需要一份数据,所以只需要一份 offset
        // 在不存储更多信息的情况下,你不知道全局的 uniform buffer 是否存在,即使它存在,你也不知道全局的 uniform buffer 的 offset 的 index 是什么
        // 因此这里直接把整个 globalOffsets 拷贝到这一个物体所对应的整个 offset 区间中
        // 假设当前使用的 shader 没有全局的 uniform buffer,那么 dynamicOffsets 这一段区间最终也会赋为被非全局的 uniform buffer 的 offset
        // 假设当前使用的 shader 有全局的 uniform buffer,那么 dynamicOffsets 这一段区间上,某一个位置会是全局的 uniform buffer 的 offset,
        // 剩下的位置会被非全局的 uniform buffer 的 offset 填充
        for (uint32 offsetIndex = offsetStart; offsetIndex < offsetStart + dynamicOffsetCount; ++offsetIndex)
        {
            dynamicOffsets[offsetIndex] = globalOffsets[offsetIndex - offsetStart];
        }
    }

最终做出来的 dynamicOffsets 会被提供给 vkCmdBindDescriptorSets

vkCmdBindDescriptorSets 是逐物体的,因为绘制命令是逐物体的

perObjectIndexes

这里用一个 perObjectIndexes 来存储这一帧的物体的数量

看上去不必要用 vector,直接用一个 int 就好了

类似他有一个 int32 offsetStart = objIndex * dynamicOffsetCount; 就很精炼

提取出了第 i 个物体的

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值