一、Pipeline简介
Vulkan中的管线分为两种:Compute Pipeline 和 Graphics Pipeline。
这两种Pipeline的作用跟其他CG API并没有太大的差别。
Compute Pipeline 用于异构并行计算,Graphics Pipeline 用于绘制渲染。
1.1 Compute Pipeline
1965年英特尔(intel)创始人之一的戈登·摩尔提出著名的摩尔定律:集成电路上可容纳的元器件的数量每隔18至24个月就会增加一倍,性能也将提升一倍。
从此,摩尔定律成为了推动半导体行业发展的“自我实现”的预言。
但是随着行业的发展,摩尔定律越来越难以实现。2019年英伟达(Nvidia)CEO黄仁勋在CES 2019展会上表示:“摩尔定律过去是每5年增长10倍,每10年增长100倍。而如今,摩尔定律每年只能增长几个百分点,每10年可能只有2倍。因此,摩尔定律结束了。”
黄仁勋声称摩尔定律已经失效,他说这番话也许有商业原因,但是一个真实的行业情况就是:在人工智能、云计算、数据挖掘、数据分析等技术兴起的背景下,CPU算力越来越捉襟见肘。
行业对算力的强烈需求,推动了异构计算技术的发展。
Vulkan在设计之时就已经将支持异构并行计算纳入考虑范围。Compute Pipeline就是为此而生。
Vulkan 的Compute Pipleline比较简单,API也比较少,基本上我们只需要关注shader本身就好。
1.2 Graphics Pipeline
相比于Compute Pipleline,Vulkan的Graphics Pipeline更加复杂,Rasterzation(光栅化)、Shading(着色)、Geometry (几何着色)、Tessellation (细分)... ... 这些年虐过你的功能一个不少。
在Vulkan中,配置Graphics Pipeline需要三个步骤:
- 提供shader
- 绑定资源
- 管理状态
后两者是本文要讲的重点。
二、Pipeline State Management
从早期开始,OpenGL 状态机就提供了更细颗粒度的状态控制。
精细颗粒度的控制对驱动程序带来了负担,驱动程序不得不对状态进行缓存和运行时编译(JIT)。
但是现在新的API,几乎把整个GPU state vector封装到一个object中。
比如,如果你想切换状态,是通过切换pipeline state A和pipeline state B。而不是想OpenGL中那样更改标志位。
这样粗颗粒度的状态对象的优势是方便驱动程序的编译和验证,有助于避免在状态改变时造成的暂停现象。
Vulkan的Pipeline状态管理参考的是Mantel,提供了Pipeline State Object(PSO)进行状态管理:
- Vertex input state
- Vertex input state用来管理Vertex数据的位置、索引、布局等信息
- Input assembly state
- Input assembly state管理定点数据的组织方式(点、线、三角形...)
- Tessellation State
- Tessellation State管理Tessellation control shader 和 Tessellation evaluation shader的状态
- Rasterization state
- Rasterization state用来管理光栅化的一些状态,包括多边形的填充模式(PolygonMode)、剔除模式(正面剔除、背面剔除)、深度信息的处理
- Color Blend state
- Color Blend是Vulkan Graphics Pipeline的最后阶段,这个阶段负责将片段写入color attachments。在许多情况下,这是一个简单的操作,仅用Fragment Shader输出的值覆盖attachments中的值。除此之外,color blend还可以将这些值与FrameBuffer中的值混合,并进行简单的逻辑运算。
- Viewport state
- Viewport state用来管理Viewport,Viewport会将设备坐标(device coordinate)转换为窗口坐标(window coordinate),是进行光栅化之前最后一次坐标变换
- Depth/Stencil state
- Depth/Stencil state控制着Depth和Stencil测试的方式
- Multi-Sampling State
- 多重采样的目的是为了抗锯齿,Multi-Sampling State管理多重采样
Dynamic state
- Graphics Pipeline很复杂,包含很多状态,一些图形应用希望能以更高的频率更改某些状态。如果每种状态更改都要创建一个新的Pipeline对象,非常不利于管理。
- Dynamic state可以管理viewport、stencil、line widths(线宽)、blending constants、stencil comparison masks等状态。应用无需重建Pipeline对象,只需要通过Command Buffer就可以实现状态更新
三、Resource Binding
Vulkan的资源绑定涉及到以下几个概念:
- Descriptor
- Descriptor Set
- Descriptor set layout
- Descriptor binding
- Pipeline layout
- Push constant
了解DirectX12(D3D12)的同学更容易接受Descriptor Set、Descriptor binding这些概念,因为Vulkan的绑定模型(Binding model)一部分参考了DirectX12(D3D12)的设计理念。
3.1 Descriptor
Descriptor是一个GPU特定编码格式的数据块。Descriptor所指的内容不同,就可以表示不同的数据类型。比如指向纹理的texture descriptor可能包括指向纹理数据的指针,以及宽度/高度,格式等信息。
由于不同的GPU存储信息的方式不同,所以API中并没有对应用暴露format信息。
Descriptor的内存不可以分配和释放,只能write,copy 和 move。
3.2 Descriptor Set
Descriptor Set是一个绑定在Pipeline上资源集合。多个Descriptor Set可以同时绑定到一个Pipeline上。
每个Descriptor Set都有一个layout,Descriptor set Layout会控制当前资源集中的资源排布方式,给shader提供了读取资源的接口。
Descriptor set layout本质上是Descriptor bindings的集合。Descriptor binding可以是一个 texture descriptor、buffer descriptor或者sampler descriptor等descriptor。
正是通过Descriptor binding,Descriptor Set才实现了shader和资源的绑定,方便了shader对资源的读写操作。
3.3 Pipeline layout
Pipeline layout是由Pipeline可以访问的由descriptor set layouts 和 push constant ranges组成,它表示Pipeline可以访问的完整资源集。
其中,Push constant 提供了一个快速更新shader中常量的方法。
3.4 Binding model
我们把上述元素组织在一起,就是vulkan资源的绑定模型。
Descriptor Set包含一组Descriptor和Descriptor Set layout:
- 每个Descriptor都可以表示不同的数据类型
- Descriptor Set Layout由Descriptor binding组成,会控制每个Descriptor的排列方式
- Descriptor binding将Descriptor和shader进行绑定,给shader提供了对资源操作的接口。
Constants register array(Root Table) 把多个Descriptor Set 和 push constant组织在一起。
Pipeline layout 表示整个渲染管线的资源布局。
最后我们来看一下整体架构的示意图:
参考文档:
- Vulkan Programming Guide
- Vulkan Cookbook
- Learning Vulkan
- Vulkan® 1.1.148 - A Specification
- Vulkan Rendering Interface
- Managing Descriptor Heaps
- 21-LowLevelAPIs
- Vulkan Tutorial
- Qualcomm Vulkan Tutorial
- Choosing a binding model
- Elements of design of explicit graphics APIs
- Binding models investigation
- SIGGRAPH 2015
- Getting started with computer graphics and the vulkan API
- Descriptor binding: DX12 and Vulkan