大量數據+同步+多線程_Vulkan 多線程渲染

db60bec931e093d60fcec4d16329f294.png

1. Overview of Vulkan

1.1 計算機圖形軟件

圖形軟件有兩個大類:專用軟件包(special-purpose packages)和通用編程軟件包(general programming packages)。

專用軟件包通常提供一種UI設計語言,讓用戶直接生成想要的圖形,不用關心內部實現。這類軟件例子是PS、CAD等等。

相反,通用編程軟件包提供一個可使用C、C++或Java等高級語言編程的圖形函數庫。圖形函數庫中提供幾何圖元、矩陣變換等操作,提供了間接操作硬件的軟件接口,所以這組圖形函數又被稱為計算機圖形應用編程接口(computer-graphics application programming interface,CG API)。OpenGL、Vulkan、DirectX、Metal皆在此列。

1.2 Vulkan多線程的設計理念

Vulkan不僅僅是圖形(graphics)API,而是一個面向圖形和計算的編程接口(graphics and compute)。支持Vulkan的設備可以是GPU,也可以是DSP或者固定功能的硬件。

Vulkan中的計算模型主要基于并行計算,因此支持多線程是Vulkan設計的核心理念之一。

為了較少Vulkan內部因為互斥同步等操作造成的卡頓問題,Vulkan內部默認認為對任何資源的訪問不存在多線程競爭,所有的資源同步操作由應用開發者去負責,因為對資源的訪問和使用沒有人比應用開發者自己更加清楚。Vulkan稱之為外部同步(external synchronization)。

因為這個原因,資源管理和線程同步工作成為編寫Vulkan程序的最大難點之一。想要讓Vulkan多線程正常運行,你需要做大量的工作。當然,換來的是Vulkan有了更加干凈的線程模型以及比其它CG API高得多的性能。

5e679ceb9862ea3af2c36fa349075881.png
image-20200730105359314.png

1.3. Instances, Devices, and Queues

在正式研究Vulkan多線程之前,有三個重要的基礎概念需要了解—Instances, Devices, and Queues。

Instances可以看做是應用的子系統,從邏輯上把Vulkan與應用程序上下文中的其他邏輯隔開。Instances可以看做是Vulkan的上下文,它會跟蹤所有狀態,從邏輯上把所有支持Vulkan的設備整合在一起。

Devices有兩個概念:Physical devices和Logical device。

Physical devices通常代表一個或者多個支持Vulkan的硬件設備,這些設備具有特定功能,可以提供一系列Queues。圖形顯卡、加速器、DSP等都可以是Vulkan的Physical devices。

Logical device是Physical devices的軟件抽象,用于預訂一些硬件資源。

Queues可以理解為一個“GPU線程”,它是實現Vulkan多線程的關鍵元素之一,用于響應應用的請求,大部分時間,應用都在與其交互。

Vulkan功能的層次結構圖如下:

d6c879b05ad44fe651634d5c6e89cdcb.png
image-20200730105801733.png

2. Queues and Command Buffer

2.1 Queues

Queue代表一個GPU線程,Vulkan設備執行的就是提交到Queues中的工作。物理設備中Queue可能不止一個,每一個Queue都被包含在Queue Families中。

Queue Families是一個有相同功能的Queues的集合,它們的性能水平和對系統資源的訪問是相同的,并且在它們之間數據傳輸工作沒有任何成本(同步之外)。

一個物理設備中可以存在多個Queue Families,不同的Queue Families有不同的特性。相同Queue Families中的Queues的功能相同,并且可以并行運行。

按照Queue的能力,可以將其劃分為:

  • Graphics(圖形)
    • 該系列中的Queues支持圖形操作,例如繪制點,線和三角形。
  • Compute(計算)
    • 該系列中的Queues支持諸如computer shader之類的計算操作。
  • Transfer(傳輸,拷貝)
    • 該系列中的Queues支持傳輸操作,例如復制緩沖區和圖像內容。
  • Sparse binding(稀疏綁定)
    • 該系列中的隊列支持用于更新稀疏資源(sparse resource)的內存綁定操作。

ab77721e7ff093fbfc201dbaae84da64.png
image-20200730112126405.png

2.2 Command Buffer

2.2.1 單線程的性能瓶頸

傳統CG API是單線程的,性能的提升只能依賴于CPU主頻的提高。能有的優化方案也不外乎主線程和渲染線程分開,或者某些資源的異步加載、離線處理。

a1ce1e5b3af62a42b7e0766fe983bb05.png
image-20200730114946379.png

但是在實際應用中我們還是經常遇到傳統CG API導致的性能瓶頸。

以手機終端為例,CPU主頻提升有限,各大芯片廠商開始向多核多線程發展,考慮到功耗溫控問題,又不能把CPU頻率升的太高,越來越高的刷新率對實時渲染的速度要求越來越苛刻。

cfe7723f6ae73c61cfded18cd7241c06.png
image-20200730115516772.png

Vulkan為了充分發揮CPU多核多線程的作用,引入了command buffer的概念。多個線程可以同時協作,每個CPU線程都可以往自己的command buffer中提交渲染命令,然后統一提交到對應的Queue中,大大提高了CPU的利用率。

2b65b4e90e128cfb0c6d503df3eb37a0.png
image-20200730115609709.png

2.2.2 Command Buffer的作用

應用在繪制時會提交一系列繪制命令給GPU驅動,但是這些繪制命令不會立刻被執行,而是被簡單的添加到Command Buffer的末尾。

在其他CG APIs中,驅動程序在應用不感知的情況下,把API調用翻譯成GPU command并儲存在command buffer中,最終提交給GPU處理。command buffer的創建和銷毀都由驅動負責。

在Vulkan中,你需要自己從Command Buffer Pool中申請command buffer,將想要記錄的命令放入command buffer中。

Command Buffer Pool:

da156a37f32a7a6c0b99b870bb6cde23.png
image-20200730142932026.png

2.2.3 Recording command

Command Buffer可以記錄(Record)很多命令,比如:設置狀態、繪制操作、數據拷貝...

82a2e61d08ceb074909f5e19b4788cce.png
image-20200730142958943.png

f64cb94d69ff77c940b889a979262f23.png
image-20200730142302468.png

理論上,一個線程可以把Command記錄到多個Command Buffer中,多個線程也可以共享同一個Command Buffer,但是一般不鼓勵多個線程共享一個Command Buffer。

Vulkan的關鍵設計原則之一就是做到高效的多線程。想實現這一點,應用程序要注意因為資源競爭導致的多線程彼此阻塞。因此,每個線程最好有一個或者對個Command Buffer,不要嘗試共享一個。另外,Command Buffer由Command Buffer Pool分配,應用可以為每一個線程創建一個Command Buffer Pool,讓各個工作線程從Command Buffer Pool中分配Command Buffer,無需參與競爭。

cd2831cfeede916a0736a081031404ea.png
image-20200730144149412.png

2.2.4 Submitting Command Buffers

提交過程使用示意圖更加好理解一點。

單線程Command Buffer提交過程:

7a2a9348c334a51738a38e71a815dfab.png
submit cb1.PNG

b060f7f6f4f79674d2607e5386ad3a10.png
submit cb5.PNG

79a28aaa8e3f1b8924bb2330ba452fb4.png
submit cb2.PNG

多線程Command Buffer提交過程:

e852158ae1ef6115828cfbcf792940b7.png
submit cb3.PNG

91e33166a056dce1b367cc9d57f04233.png
submit cb4.PNG

整體流程如下:

0e591a910f2e551d478d1bbadb755955.png
image-20200730144906368.png

3. Synchronization

3.1 顯示同步操作

Vulkan把同步的操作交給了應用(external synchronization),絕大多數的Vulkan命令根本不提供同步,需要應用自己負責。Vulkan給應用提供了同步原語,幫助應用進行同步操作。

Vulkan中主要有四種同步原語(synchronization primitives):

  • Fences
    • 最大顆粒度的同步原語,目的是給CPU端提供一種方法,可以知道GPU或者其他Vulkan Device什么時候把提交的工作全部做完。
    • 如果你熟悉Android顯示機制的話,acquire fence或者retire fence就是類似的作用
  • Semaphores
    • 顆粒度比Fences更小一點,通常用于不同Queue之間的數據同步操作
  • Events
    • 顆粒度更小,可以用于Command Buffer之間的同步工作
  • Barriers
    • Vulkan流水線(Pipeline)階段內用于內存訪問管理和資源狀態移動的同步機制

下面這張圖取自NVIDIA公司Vulkan 多線程講解的PPT:

71b932808bab26258a41d2d7e892cb64.png
image-20200730145823767.png

3.2 隱藏的執行順序

Vulkan是顯式的API沒錯,號稱是“沒有秘密的API”。但是在多線程同步時,還是存在一些潛規則。

以下面這張圖為例,同一個Queue中,Command Buffer1 和Command Buffer2 誰先執行?Command Buffer中記錄的一堆命令是如何執行的?

0e591a910f2e551d478d1bbadb755955.png
image-20200730144906368.png

Vulkan的執行順序其實是有一定的潛規則的,在沒有同步原語的情況下:

  • Command Buffer中的Command,先記錄的先執行
  • 先提交的Command Buffer先執行
  • 同一個Queue中,一起提交的Command Buffer1 和Command Buffer2 按照下標的順序執行,Command Buffer1 先執行

3.3 Barriers

所有的同步原語中,Barriers使用起來最為困難。Barriers用于顯式的控制buffer或者image的訪問范圍,避免hazards(RaW,WaR,and WaW),保證數據一致性。

Barriers需要開發者了解渲染管線的各個階段,能清晰的把握管線中每個步驟對資源的讀寫順序。

Vulkan中將Pipeline的各個階段定義為:

  • TOP_OF_PIPE_BIT
  • DRAW_INDIRECT_BIT
  • VERTEX_INPUT_BIT
  • VERTEX_SHADER_BIT
  • TESSELLATION_CONTROL_SHADER_BIT
  • TESSELLATION_EVALUATION_SHADER_BIT
  • GEOMETRY_SHADER_BIT
  • FRAGMENT_SHADER_BIT
  • EARLY_FRAGMENT_TESTS_BIT
  • LATE_FRAGMENT_TESTS_BIT
  • COLOR_ATTACHMENT_OUTPUT_BIT
  • TRANSFER_BIT
  • COMPUTE_SHADER_BIT
  • BOTTOM_OF_PIPE_BIT

對應:

ac1aa4752cffd80b2c747ac3ff7f0064.png
image-20200730152820973.png

假設我們有個兩個渲染管線P1 和 P2,P1會通過Vertex Shader往buffer寫入頂點數據,P2需要在Compute Shader中使用這些數據。

如果使用fence去同步,你的流程應該是這樣:P1的Command提交后,P2通過fence確保P1的操作已經被全部執行完,再開始工作。

cfd35803fcdad7eb088d274d1503542e.png
image-20200730153109052.png

但是這種大顆粒度的同步操作無疑造成了耗時操作:P1的數據在Vertex Shader階段就已經準備好了,我們為什么要等到它所有操作執行完再開始?P2平白多等待了很長時間,而且在這個期間P2的其他階段并沒有使用到P1的數據,也是可以執行的啊。

Barriers的引入完全解決了這個問題,我們只需要告訴Vulkan,我們在P2的Compute Shader階段才會等待P1 Vertex Shader里面的數據,其他階段并不關心,可以同步進行。

71244dca8322a9e45ad93d3e5bd8c6ec.png
image-20200730152521195.png

使用方法:

ed769e91d1f27690205f2c98c5bef611.png
image-20200730153743130.png

參考文檔:

  1. Vulkan Overview
  2. Android and Vulkan - GDD China.pdf
  3. Vulkan Programming Guide
  4. Vulkan Cookbook
  5. Learning Vulkan
  6. Vulkan Multi-Threading
  7. Vulkan中的同步機制
  8. Vulkan? 1.1.148 - A Specification
  9. VULKAN BARRIERS EXPLAINED
  10. vulkan中的同步和緩存控制之二,barrier和event
  11. Xinzhao:vulkan中的同步和緩存控制之一,fence和semaphore

本系列文章匯總:

  • Vulkan 簡介
  • Vulkan 多線程渲染
  • Vulkan 內存管理
  • Vulkan 繪制與顯示
  • Vulkan 資源綁定和狀態管理

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/455430.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/455430.shtml
英文地址,請注明出處:http://en.pswp.cn/news/455430.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

飛康任命Gartner前分析師擔任亞洲區市場總監

在虛擬化、數據保護和數據遷移領域具備15年創新經驗的美國飛康軟件公司(FalconStor Software, Inc.,NASDAQ:FALC)近日宣布任命張瑾(Jimmie Chang)先生擔任該公司亞洲區市場部門負責人。 飛康公司近日面向全…

12_登陸案例

13131轉載于:https://www.cnblogs.com/ZHONGZHENHUA/p/7044846.html

如何基于FFMPEG和SDL寫一個少于1000行代碼的視頻播放器

http://blog.csdn.net/eplaylity/archive/2008/12/05/3454431.aspx http://www.cnblogs.com/konyel/tag/SDLGuide%E4%B8%AD%E6%96%87%E8%AF%91%E7%89%88/ ffmpeg文檔http://blog.sina.com.cn/s/blog_46dc65a90100a91b.html http://dranger.com/ffmpeg/ffmpeg.html VLC核心功能部…

Flask 概述

什么是Web Framework? Web Application Framework(Web應用程序框架)或簡單的Web Framework(Web框架)表示一個庫和模塊的集合,使Web應用程序開發人員能夠編寫應用程序,而不必擔心協議&#xff0…

(五)Maven中的聚合和繼承

一、為什么要聚合? 定義:我們在開發過程中,創建了2個以上的模塊,每個模塊都是一個獨立的maven project,在開始的時候我們可以獨立的編譯和測試運行每個模塊,但是隨著項目的不斷變大和復雜化,我們…

python堆棧反向輸出列表_python - IPython:將Python腳本的輸出重定向到文件(如bash) - 堆棧內存溢出...

IPython有自己的上下文管理器來捕獲stdout / err ,但它沒有重定向到文件,它重定向到一個對象:from IPython.utils import iowith io.capture_output() as captured:%run my_script.pyprint captured.stdout # prints stdout from your script…

關于datagrid

基本在公司使用的datagrid不需要自己寫前臺代碼,只需要自己給grid明確id,url以及列屬性即可。 后臺需要返回一個數據類型:{recordsFiltered2, data[], drawnull, recordsTotal2},通常返回這個數據類型的話,只需要調用d…

M-JPEG、MPEG4、H.264都有何區別 依維安防論壇

壓縮方式是網絡視頻服務器和網絡攝像機的核心技術,壓縮方式很大程度上決定著圖像的質量、壓縮比、傳輸效率、傳輸速度等性能,它是評價網絡視頻服務器和網絡攝像機性能優劣的重要一環。 隨著多媒體技術的發展,相繼推出了許多壓縮編碼標準&…

Django/Flask/Tornado三大web框架性能分析

寫在前面:本文的數據涉及到之前遇到過的問題,大概一次 http 請求到收到響應需要多少時間。這個問題在實際工作中與框架有比較大的關系,因此特別就框架的性能做了一次分析。這里使用之前的一個報告數據: Pythons Web Framework Ben…

python urllib模塊學習筆記

這個模塊是最基本最常用的,以前看過,總結一下 #coding : utf-8import urlliburl http://cnblogs.com#代理服務器proxies {http:http://127.0.0.1:8087}#使用代理服務器打開r urllib.urlopen(url,proxies proxies)print r.info()print r.getcode()pri…

hibernate基礎工具findBySQL學習

public List<Map<String,Object>> findBySQL(String sql,Map<String,Object> param,int start,int max) {log.debug("finding List by hql");try {       //最后返回map map的key可為別名和數據庫字段SQLQuery querysessionFactory.getCurr…

python處理ini文件_python對ini配置文件處理

>>> cf.read("test.ini") #讀取配置文件[test.ini]>>> cf.sections() #片段名[base, callback]>>> cf.options("callback") #配置…

Python實現自動推本地github博客到遠程倉庫

Python實現自動推本地github博客到遠程倉庫 以前的簡單版本 通過python中的os模塊操作系統命令 詳情可參考:Python實現一行代碼推本地git到遠程倉庫 升級版本 本次加入了監聽文件修改功能 這樣腳本只需在后臺運行,即可檢測到對應的文件夾中的內容是否變化 如果變化,則調用…

H.264/MPEG-4 AVC

維基百科&#xff0c;自由的百科全書跳轉到&#xff1a; 導航, 搜索 跳過字詞轉換說明 漢漢▼▲為了閱讀方便&#xff0c;本文使用全文手工轉換。轉換內容&#xff1a;本文采用電腦和信息技術組全文轉換 [查看] ? [編輯] ? [強制刷新] 以下為本條目單獨的全文轉換&#xff0c…

JavaScript 專題之函數柯里化

JavaScript 專題系列第十三篇&#xff0c;講解函數柯里化以及如何實現一個 curry 函數 定義 維基百科中對柯里化 (Currying) 的定義為&#xff1a; In mathematics and computer science, currying is the technique of translating the evaluation of a function that takes m…

機器學習模板

根據心情補充&#xff0c;語言都是Python hash&#xff0c;把所有的文本轉化成數字 from sklearn.preprocessing import LabelEncoder for c in train.columns:if train[c].dtype object:lbl LabelEncoder()lbl.fit(list(train[c].values) list(test[c].values))train[c] l…

漂亮特殊字體可復制_12個創意字體免費下載網站

今天為大家介紹12個創意字體的網站&#xff0c;這些網站都有提供免費下載的字體哦&#xff0c;希望對大家在創作上面有所幫助。FontSpace在Fontspace上有超過42000種免費字體。在這里字體被整齊的分門歸類&#xff0c;幫助你找到想要的字體。除了典型的“serif” “script”等&…

使用postman測試接口

Postman是一款功能強大的網頁調試與發送網頁HTTP請求的Chrome插件。在java web開發中使用非常多&#xff0c;經常用來測試接口。 使用postman模擬json數據的發送 第一步:在header里邊設置發送數據的類型 Paste_Image.png設置發送數據類型為json&#xff0c;也就是key為Content-…

刪除github上的commit歷史記錄

刪除github上的commit歷史記錄 起步 今天小編發現了git克隆下來的遠程庫特別大: 經過查詢之后發現是每次推送之后都會留下記錄緩存&#xff0c;這樣很多沒用的記錄就會占用多余的空間&#xff0c;別人克隆的時候也會多耗費時間&#xff0c;今天我查到了一個清除無用記錄的方…

DirectShow組件原理分析及應用

1 DirectX簡介  DirectX是Microsoft公司為游戲和其他高性能多媒體應用所提供的一套底層應用程序編程接口。這些接口包括對二維和三維圖形&#xff0c;聲效和音樂&#xff0c;輸入設備以及多玩家網絡游戲等的支持。目前DirectX的最高版本是DirectX 9.0。  1.1 DirectX的組成…