Vulkan 总结

发布于

一、Vulkan 对象简介

1、VKInstance 这个对象是我们 Vulkan api 的一个对象,用于通过 Instance 我们与 Vulkan 底层进行交互。

2、VkPhysicalDevice 对应我们当前设备(PC、手机)的一个显卡硬件(GPU ),有的设备有多个显卡那么我们就能获得多个 VkPhysicalDevice 对象,这时候我们需要按自己的需求去选择最适合我们渲染需要的 GPU 了。

3、VKDevice 我们称之为 逻辑设备,是用来和 VkPhysicalDevice GPU硬件交互的一个对象。

4、Queue、QueueFamily 在逻辑设备上,我们有多种提交 渲染命令的队列类型、Graphic (图形绘制)、Compute(计算)、Transfer(传输) 、SparseBinding(还不太了解),在Vulkan 中一个Queue 只能在一个线程中操作,多个线程需要分别分配多个Queue 使用,提交,queue中提交的命令只能保证按提交顺序开始执行,然后不保证每个命令的执行结束的顺序,所以如果有相互依赖的需要自己通过同步源语 Semaphore、Barrier、Fence 等控制。

5、VKSurfaceKHR 用于渲染的窗口表面,通过我们创建的 window 创建。在构建交换链的时候需要一个窗口表面VKSurfaceKHR

6、Sswapchain 为了我们图像呈现的一个缓冲对象,OpenGL 是内置了两个交换缓冲区的方案,而Vulkan 对这个交互缓冲对象给我更多的定制细节,比如 我们可以选择生成更多的绘制缓冲区 (swap image), 也能选择我们我们缓冲区交换呈现的方式 VkPresentModeKHR。

7、Pipeline 渲染管线对象,这个对象构成比较复杂,包含了 管线各个阶段的着色器对象,各个阶段的管线状态模式,比如 rasterizer(光栅化状态)、depth stencil (深度模板状态)、blend (颜色融合状态)、mutile state(多重采样状态,这个是Vulkan特有的状态,OpenGL 不能直接在管线状态层设置多重采样,只能全局设置开启),另外就是 PipelineLayout、RenderPass

8、RenderPass 这个概念是一个比较复杂的对象,在我们复杂的绘制过程成,我们会画多幅画,然后相互之间可能会有引用关系,比如绘制阴影的时候,我们需要先绘制一遍获得一个深度图,然后通过深度图作为输入,再绘制物体,绘制物体的时候通过深度图计算最终的颜色。这里一个绘制过程我们称之为一个SubPass。RenderPass 就是用来组织这多个 SubPass 用的,他告诉渲染管线,我有几个纹理附件(image)有几次绘制过程(几个Subpass),他们之间是一个什么样的依赖关系。

9、PipelineLayout 是用来描述,在渲染管线中,我们需要的 uniform、定点输入信息、采样纹理等信息有哪些,并且他们是怎么布局的,这样底层shader 绘制的时候直接按照 这个布局去取信息即可。为了细分这些信息,PipelineLayout 又分出了 DescriptorSetLayout 把信息又分成一堆一堆的的。一个 DescriptorSetLayout 描述了一组信息的布局,然后有了 DescriptorSetLayout 那肯定就有对应的DescriptorSet,这个DesciptorSet 代表了它维护的信息和我们的 Buffer、Image怎么映射。DescriptorSet 由于是可复用对象,所以又有一个 DescriptorSetPool 方便复用.

10、CommandBuffer 用于收集渲染指令用的对象,因为Vulkan 的渲染需要通过收集一系列的命令然后通过 Queue 提交给硬件去执行的。同样CommandBuffer 也是可复用的,所以他也有个 CommandPool 的对象管理。

11、Semaphore、 Fence 由于Vulkan 是支持多线程渲染的。所以需要同步对象,其中 Semaphore 主要用于 GPU 内部直接的同步使用,Fence 主要通过 app 层和 GPU 进行同步,此外在 GPU 内还有一个叫 Barrier 的东西,可以达到GPU 内部的同步,他和 Semaphore 不同的是它更细致话,可以控制,Buffer、Image 在管线哪个状态的时候需要等待 Buffer\Image 需要达到什么状态才能进入到另一个管线状态。

12、Buffer 是vulkan 中的资源对象,是一个 数据段。存放 顶点数据、uniform buffer 数据等。Vulkan中Buffer 是可以设置各种属性的,比如 GPU、CPU 中的可见性、buffer 的连贯性等。通过这些细节,我们可以根据我们自己的需求设置,从而是buffer 更高效的使用

13、Image、ImageView、Sampler, Image也是一个资源对象,主要是同于存储纹理贴图信息。ImageVIew 是 Image 的使用助手,告诉使用 Image的对象,如何访问Image 中的数据,比如我通过ImageView 设置访问 Image 中模块区域给其他对象使用(有点类似自图集)。
14、FrameBuffer 这个和OpenGL 有点类似,只是Vulkan FrameBuffer 需要对应一个RenderPass。

遇到的问题

1、由于 Vulkan 对各种资源的使用都会有一个助手对象,详细描述了资源的格式布局等,只要对应不上都会异常并报错,所以一定要在开发阶段开启 VK_LAYER_KHRONOS_validation 并注册 VkDebugUtilsMessengerEXT 对象,监听异常消息的回调。即使在报错的地方触发回调回来,方便定位问题所在。没有这个找问题大海捞针的难。

2、Vulkan 底层是 惰性检查,也就是他都是想当然的(估计为了底层性能)。所以他如果对象是定义了顺序id 的你传递给他一定要排序。否则它就是告诉你不对。比如,PipelineLayout 中的DescriptorSetLayout 每个 set 都有一个 index, 那你的 DescriptorSetLayout 这个数组对象,一定要按Set index 排序。否则就有问题,还有 DescriptorSet 里面的 DescritporSetBinding 也是有顺序的也要排好序。

3、vulkan 和 NDC y 轴坐标 是 从上往下的,而OpenGL 是从下往上的。如果做gfx 推荐看这篇文章https://zhuanlan.zhihu.com/p/574067652

4、如果 你的 Image 是设置了 miplevels 的那你一定要记得 自己生成 mipmaps texture,否则 mipmap texture 就是黑的。导致3d 模型根据远近选择不同的 mipmap texture 采样,然后除了 level 1 正常,其他都是黑的。最终你的模型结果就是

这里整个模型出现很多黑色的地方,这个问题困扰了我很长时间,开RenderDoc 各种检查管线状态,各种怀疑,最终才发现是忘记 generate mipmaps 了。

学习曲线

1、vulkan 入门 https://vulkan-tutorial.com/ 看这个网址,看完一遍,然后把demo 抄了一遍。这里主要是对 vulkan 的各种概念有所有了解,通过简单的demo 来掌握各种对象的使用。
2、https://github.com/KhronosGroup/Vulkan-Samples 这个是 vulkan 官方提供的demo,里面有一套简单的 vulkan api的封装,当你想封装自己的 gfx 时候看这个你会收获很大,而且里面对于多线程渲染等复杂的vulkan 使用,都有demo 代码,非常推荐看。
3、看到的不错文章收集
3.1 https://www.zhihu.com/question/424430509/answer/2223623107
3.2 https://zhuanlan.zhihu.com/p/574067652
3.3 https://www.zhihu.com/question/28024422/answer/2312781266

12
评论 2
收藏 13
  • Piccolo小助手
    欢迎加入Piccolo社区,感谢分享!
  • 马铃薯
    马铃薯
    我也正在学这个