一、Pipeline簡介
Vulkan中的管線分為兩種:Compute Pipeline 和 Graphics Pipeline。
這兩種Pipeline的作用跟其他CG API并沒有太大的差別。
Compute Pipeline 用于異構(gòu)并行計(jì)算,Graphics Pipeline 用于繪制渲染。

1.1 Compute Pipeline
1965年英特爾(intel)創(chuàng)始人之一的戈登·摩爾提出著名的摩爾定律:集成電路上可容納的元器件的數(shù)量每隔18至24個月就會增加一倍,性能也將提升一倍。
從此,摩爾定律成為了推動半導(dǎo)體行業(yè)發(fā)展的“自我實(shí)現(xiàn)”的預(yù)言。
但是隨著行業(yè)的發(fā)展,摩爾定律越來越難以實(shí)現(xiàn)。2019年英偉達(dá)(Nvidia)CEO黃仁勛在CES 2019展會上表示:“摩爾定律過去是每5年增長10倍,每10年增長100倍。而如今,摩爾定律每年只能增長幾個百分點(diǎn),每10年可能只有2倍。因此,摩爾定律結(jié)束了?!?/p>
黃仁勛聲稱摩爾定律已經(jīng)失效,他說這番話也許有商業(yè)原因,但是一個真實(shí)的行業(yè)情況就是:在人工智能、云計(jì)算、數(shù)據(jù)挖掘、數(shù)據(jù)分析等技術(shù)興起的背景下,CPU算力越來越捉襟見肘。
行業(yè)對算力的強(qiáng)烈需求,推動了異構(gòu)計(jì)算技術(shù)的發(fā)展。
Vulkan在設(shè)計(jì)之時就已經(jīng)將支持異構(gòu)并行計(jì)算納入考慮范圍。Compute Pipeline就是為此而生。
Vulkan 的Compute Pipleline比較簡單,API也比較少,基本上我們只需要關(guān)注shader本身就好。
1.2 Graphics Pipeline
相比于Compute Pipleline,Vulkan的Graphics Pipeline更加復(fù)雜,Rasterzation(光柵化)、Shading(著色)、Geometry (幾何著色)、Tessellation (細(xì)分)... ... 這些年虐過你的功能一個不少。

在Vulkan中,配置Graphics Pipeline需要三個步驟:
- 提供shader
- 綁定資源
- 管理狀態(tài)
后兩者是本文要講的重點(diǎn)。
二、Pipeline State Management
從早期開始,OpenGL 狀態(tài)機(jī)就提供了更細(xì)顆粒度的狀態(tài)控制。

精細(xì)顆粒度的控制對驅(qū)動程序帶來了負(fù)擔(dān),驅(qū)動程序不得不對狀態(tài)進(jìn)行緩存和運(yùn)行時編譯(JIT)。
但是現(xiàn)在新的API,幾乎把整個GPU state vector封裝到一個object中。
比如,如果你想切換狀態(tài),是通過切換pipeline state A和pipeline state B。而不是想OpenGL中那樣更改標(biāo)志位。
這樣粗顆粒度的狀態(tài)對象的優(yōu)勢是方便驅(qū)動程序的編譯和驗(yàn)證,有助于避免在狀態(tài)改變時造成的暫停現(xiàn)象。
Vulkan的Pipeline狀態(tài)管理參考的是Mantel,提供了Pipeline State Object(PSO)進(jìn)行狀態(tài)管理:
- Vertex input state
- Vertex input state用來管理Vertex數(shù)據(jù)的位置、索引、布局等信息
- Input assembly state
- Input assembly state管理定點(diǎn)數(shù)據(jù)的組織方式(點(diǎn)、線、三角形...)
- Tessellation State
- Tessellation State管理Tessellation control shader 和 Tessellation evaluation shader的狀態(tài)
- Rasterization state
- Rasterization state用來管理光柵化的一些狀態(tài),包括多邊形的填充模式(PolygonMode)、剔除模式(正面剔除、背面剔除)、深度信息的處理
- Color Blend state
- Color Blend是Vulkan Graphics Pipeline的最后階段,這個階段負(fù)責(zé)將片段寫入color attachments。在許多情況下,這是一個簡單的操作,僅用Fragment Shader輸出的值覆蓋attachments中的值。除此之外,color blend還可以將這些值與FrameBuffer中的值混合,并進(jìn)行簡單的邏輯運(yùn)算。
- Viewport state
- Viewport state用來管理Viewport,Viewport會將設(shè)備坐標(biāo)(device coordinate)轉(zhuǎn)換為窗口坐標(biāo)(window coordinate),是進(jìn)行光柵化之前最后一次坐標(biāo)變換
- Depth/Stencil state
- Depth/Stencil state控制著Depth和Stencil測試的方式
- Multi-Sampling State
- 多重采樣的目的是為了抗鋸齒,Multi-Sampling State管理多重采樣
Dynamic state
- Graphics Pipeline很復(fù)雜,包含很多狀態(tài),一些圖形應(yīng)用希望能以更高的頻率更改某些狀態(tài)。如果每種狀態(tài)更改都要創(chuàng)建一個新的Pipeline對象,非常不利于管理。
- Dynamic state可以管理viewport、stencil、line widths(線寬)、blending constants、stencil comparison masks等狀態(tài)。應(yīng)用無需重建Pipeline對象,只需要通過Command Buffer就可以實(shí)現(xiàn)狀態(tài)更新
三、Resource Binding
Vulkan的資源綁定涉及到以下幾個概念:
- Descriptor
- Descriptor Set
- Descriptor set layout
- Descriptor binding
- Pipeline layout
- Push constant
了解DirectX12(D3D12)的同學(xué)更容易接受Descriptor Set、Descriptor binding這些概念,因?yàn)閂ulkan的綁定模型(Binding model)一部分參考了DirectX12(D3D12)的設(shè)計(jì)理念。
3.1 Descriptor
Descriptor是一個GPU特定編碼格式的數(shù)據(jù)塊。Descriptor所指的內(nèi)容不同,就可以表示不同的數(shù)據(jù)類型。比如指向紋理的texture descriptor可能包括指向紋理數(shù)據(jù)的指針,以及寬度/高度,格式等信息。
由于不同的GPU存儲信息的方式不同,所以API中并沒有對應(yīng)用暴露format信息。
Descriptor的內(nèi)存不可以分配和釋放,只能write,copy 和 move。
3.2 Descriptor Set
Descriptor Set是一個綁定在Pipeline上資源集合。多個Descriptor Set可以同時綁定到一個Pipeline上。
每個Descriptor Set都有一個layout,Descriptor set Layout會控制當(dāng)前資源集中的資源排布方式,給shader提供了讀取資源的接口。

Descriptor set layout本質(zhì)上是Descriptor bindings的集合。Descriptor binding可以是一個 texture descriptor、buffer descriptor或者sampler descriptor等descriptor。
正是通過Descriptor binding,Descriptor Set才實(shí)現(xiàn)了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都可以表示不同的數(shù)據(jù)類型
- Descriptor Set Layout由Descriptor binding組成,會控制每個Descriptor的排列方式
- Descriptor binding將Descriptor和shader進(jìn)行綁定,給shader提供了對資源操作的接口。
Constants register array(Root Table) 把多個Descriptor Set 和 push constant組織在一起。
Pipeline layout 表示整個渲染管線的資源布局。
最后我們來看一下整體架構(gòu)的示意圖:

參考文檔:
- 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